为什么在输入更改时做出反应以重新呈现功能组件中的所有元素

时间:2020-03-30 12:00:28

标签: reactjs react-hooks

我试图了解如何停止重新渲染功能组件中的元素(或者也许我不需要这样做)

我对所有输入使用单个useState并共享相同的onChange处理程序。

我在表单(100+)中有大量输入字段,每当我在开发工具探查器中键入它们中的任何一个时,我都会看到它们全部都被重新渲染,这是因为这是因为在每个渲染中我的onChange处理程序都是“重新创建的”并且所有输入元素也重新呈现。 如果我尝试将其包装在useCallback中,则没有任何变化,但是如果我将输入元素包装在Rect.memo组件中,则它不会重新呈现。

    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)}</pre>
        </div>
        <div>
          <pre>single state: {JSON.stringify(singleInput, null, 2)}</pre>
        </div>
      </form>
    </div>
  );
}

picture

这里是简化的sandbox示例

我是在分析某些错误信息还是这是正常行为,我应该关注性能吗?如果这样,该如何解决?

1 个答案:

答案 0 :(得分:1)

默认情况下,React重新计算功能组件内部的所有变量。

您必须使用useCallbackuseMemo来记住变量,并仅在变量的依存关系更改时重新计算它们。

因此,您必须将onHandleInputChange包装在useCallback中(否则,您将始终重新创建它,并且该属性会在每次渲染时更新输入)。

此外,您还必须将父子功能组件包装在React.memo中。相当于PureComponent类。