【问题标题】:How do I properly prevent child rerender on change value?如何正确防止子项在更改值上重新呈现?
【发布时间】:2020-07-19 14:26:17
【问题描述】:

我正在尝试创建一个表单组件,其中添加了多个字段作为父级的子级。 父组件将保存子组件的值的状态。

如何正确保存这些值并处理状态变化而不必重新渲染所有子级?我只想重新渲染发生变化的那个。

对于文本框,我知道这是其他替代方案,但我只是将其用作重新渲染的示例。在我的真实案例中,我有一个不同的组件(切换按钮)。

我创建了一个 CodeSandbox 来分享这种行为:
https://codesandbox.io/s/blissful-black-lnvhh

【问题讨论】:

    标签: reactjs state react-functional-component


    【解决方案1】:

    React.memo 正在比较传递给组件的属性并在更改时重新呈现它(这是一个浅比较 - 但在这里并不重要)。

    在您的情况下,您在 App 组件的每次重新呈现时在 <App> 中定义 changed(),并且传递给 FormContent 的函数不一样。

    const App = () => {
      const changed = values => {
        console.log(values);
      };
    
      return (
        <div className="App">
          <FormContent onChange={changed} />
        </div>
      );
    };
    

    为避免这种情况,您可以提取 changed() 定义并将其放在组件声明之上:

    const changed = values => {
      console.log(values);
    };
    
    const App = () => {
      return (
        <div className="App">
          <FormContent onChange={changed} />
        </div>
      );
    };
    

    如果您不更改该函数中的状态,这是一个很好的解决方案。如果您想将该函数保留在组件中并停止重新渲染子组件,您应该使用useCallback 钩子。

    const changed = useCallback(() => { return (values) => console.log(values) }, []);
    

    它是为了解决这个问题而创建的。末尾的[] 是一个依赖数组,它的行为与useEffect() 中的相同。

    使用回调

    传递一个内联回调和一个依赖数组。 useCallback 将返回回调的记忆版本,仅当其中一个依赖项发生更改时才会更改。这在将回调传递给依赖引用相等性以防止不必要的渲染(例如 shouldComponentUpdate)的优化子组件时很有用。

    https://reactjs.org/docs/hooks-reference.html#usecallback

    【讨论】:

    • 很抱歉,如果不清楚。在我的示例中,我试图表示当我更改 FormContent 状态时会发生重新渲染。在应用程序中创建的更改功能只是在控制台中记录状态值的功能,因此我可以调试。我更新了示例。
    【解决方案2】:

    纯组件

    使用纯组件 API。这只会在它的 props 实际改变时重新渲染

    class MyComponent extends React.PureComponent {
    

    来自docs

    React.PureComponent 类似于 React.Component。它们之间的区别在于 React.Component 没有实现 shouldComponentUpdate(),但是 React.PureComponent 通过浅 prop 和 state 比较来实现它。

    备忘录

    如果你的组件是函数式组件,你可以使用 React.memo

    const MyComponent = React.memo(function MyComponent(props) {
      /* render using props */
    });
    

    来自docs

    React.memo 是一个高阶组件。它与 React.PureComponent 类似,但用于函数组件而不是类。

    【讨论】:

    • 我正在使用文本框中的备忘录。如果这是解决方案,是否可以编辑代码框,所以我知道我做错了什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-07
    • 2020-02-21
    • 1970-01-01
    相关资源
    最近更新 更多