Зачем реагировать на изменение входных данных всех элементов функционального компонента - PullRequest
2 голосов
/ 30 марта 2020

Я пытаюсь понять, как остановить рендеринг элементов в функциональном компоненте (или, может быть, мне не нужно?)

Я использую единственное useState для всех входов и использую один и тот же обработчик onChange.

У меня есть огромное количество полей ввода в формах (более 100), и всякий раз, когда я набираю любое из них в профилировщике инструментов разработки, я вижу, что они все перерисовываются, предполагая, что это происходит потому, что при каждом рендеринге мой обработчик onChange "воссоздается" и все входные элементы также перерисовываются. Если я попытаюсь обернуть его в useCallback, то ничего не изменится, но если я оберну свой элемент ввода в компонент Rect.memo, он не будет перерисован.

<code>    const MyInput = props => {
  return <input {...props} />;
};

const MyInputMemo = React.memo(props => {
  return <input {...props} />;
});

function App() {
  React.useDebugValue("test");

  const [formValues, setFormValues] = useState({
    name1: "test 1",
    name2: "test 2",
    name3: "test 3"
  });
  const [singleInput, setSingleInput] = useState("single input handler");

  const onHandleInputChange = e => {
    setFormValues({ ...formValues, [e.target.name]: e.target.value });
  };

  const onHandleInputChangeSingle = useCallback(e => {
    setSingleInput(e.target.value);
  }, []);

  return (
    <div className="App" style={{ padding: "30px" }}>
      <div>
        <h1>Test form</h1>
      </div>

      <form>
        <div>
          <label>shared onChange</label>
          <MyInput
            name="name1"
            value={formValues.name1}
            onChange={onHandleInputChange}
          />
        </div>
        <div>
          <label>shared onChange</label>
          <MyInput
            name="name2"
            value={formValues.name2}
            onChange={onHandleInputChange}
          />
        </div>
        <div>
          <label>shared onChange (memo)</label>
          <MyInputMemo
            name="name3"
            value={formValues.name3}
            onChange={onHandleInputChange}
          />
        </div>
        <div>
          <label>self onChanged</label>
          <input
            name="name4"
            value={singleInput}
            onChange={onHandleInputChangeSingle}
          />
        </div>
        <div>
          <pre>shared state:{JSON.stringify(formValues, null, 2)}
single state: {JSON.stringify(singleInput, null, 2)}
); }

picture

здесь упрощено песочница пример

Профилирую ли я что-то неправильно или это нормальное поведение, я должен беспокоиться о производительности и, если да, то как это исправить?

1 Ответ

1 голос
/ 30 марта 2020

По умолчанию React пересчитывает все переменные внутри функционального компонента.

Вы должны использовать useCallback и useMemo для запоминания переменных и их пересчета только в случае изменения их зависимостей.

Таким образом, вы должны обернуть onHandleInputChange в useCallback (в противном случае вы всегда воссоздаете его, и этот реквизит обновляется для входов при каждом рендеринге).

Кроме того, вы должны обернуть родительские и дочерние функциональные компоненты в React.memo , Это эквивалентно PureComponent для классов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...