Установить состояние из изменения реквизита в функциональном компоненте React?

У меня простой функциональный компонент реакции выглядит следующим образом:

import React, { useState } from "react";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <Test
        children={
          <React.Fragment>
            <label>Name: </label>
            <input type="text" onChange={(e) => setData(e)} /> 
          </React.Fragment>
        }
      />
    </div>
  );
}

export function Test({ children }) {
  const [data, setData] = useState("");
  return (
    <>
      <div>{children && children}</div>
      <div>{data}</div>
    </>
  );
}

У меня вопрос, как обновить состояние data внутри Test Component при срабатывании события onChange? Вот песочница.

Надеюсь, кто-нибудь сможет мне помочь .. Заранее спасибо


person bagongpct    schedule 01.03.2021    source источник


Ответы (2)


Вы можете использовать для этого render props технику и можете сохранить свой шаблон нетронутым, если не предпочитаете серьезный рефакторинг.

Рабочая демонстрация - https://codesandbox.io/s/flamboyant-monad-hw2lu?file=/src/App.js.

import React, { useState } from "react";
import "./styles.css";

export function Child(props) {
  const { setData } = props;
  return (
    <React.Fragment>
      <label>Name: </label>
      <input type="text" onChange={(e) => setData(e.target.value)} />
    </React.Fragment>
  );
}

export default function App() {
  return (
    <div className="App">
      <Test
        render={(props) => {
          const { setData } = props;
          return <Child setData={setData} />;
        }}
      ></Test>
    </div>
  );
}

export function Test(props) {
  const [data, setData] = useState("");
  const { render } = props;
  return (
    <>
      <div>{render({ setData })}</div>
      <div>{data}</div>
    </>
  );
}

person Diwakar Singh    schedule 01.03.2021
comment
Большое спасибо Дивакар. Это полностью работает так, как я хочу. - person bagongpct; 02.03.2021

Не обязательно так отправлять детей. В React есть особый способ работы с дочерними элементами, который проще выполнять и поддерживать. В вашем случае вам просто нужно поднять свое состояние и отправить state и callback в качестве реквизита.

import React, { useState } from "react";
import "./styles.css";

export default function App() {
 const [data, setData] = React.useState('')
  return (
    <div className="App">
      <Test data={data}>
         <> // shorthand for ReactFragment
            <label>Name: </label>
            <input type="text" onChange={(e) => setData(e.target.value)} value={data}/> 
         </>
      </Test>
    </div>
  );
}

export function Test({ data, children }) {
  return (
    <>
      <div>{children && children}</div>
      <div>{data}</div>
    </>
  );
}
person Rey Young    schedule 01.03.2021
comment
Я не хочу создавать другое состояние в родительском компоненте. Спасибо тебе, Рей - person bagongpct; 02.03.2021
comment
О, не понял этого. - person Rey Young; 02.03.2021