从功能组件发送功能道具时防止重新渲染

Prevent re-render when sending function prop from functional component

将 props 发送到 PureComponent 或功能组件时,您可以通过使用不会因每次渲染而改变的 props 来优化性能,这将防止组件重新渲染。

使用 class 组件时,这很简单:

class Component extends React.Component {
  render() {
    return <List createRows={this.createRows}/>;
  }

  createRows = () => this.props.data.map(dataToRow);
}

鉴于 ListPureCompoment 或功能组件,createRows 属性永远不会导致 List 的重新渲染。


但如果 Component 是功能组件,则不再可能:

  function Component(props) {
    return <List createRows={createRows}/>;

    function createRows() {
      return props.data.map(dataToRow);
    }
  }

由于每次 Component 渲染时都会创建 createRows,因此道具会更改,导致每次 Component 重新渲染时都会重新渲染 List。这可能会导致很大的性能损失。还要注意 createRows 不能放在函数组件之外,因为它依赖于 List.

data 属性

现在,随着 Hooks 的引入,可以将 createRows 放在 useState 钩子中:

  function Component(props) {
    const [ createRows ] = useState(() => () =>
      props.data.map(dataToRow);
    );

    return <List createRows={createRows}/>;
  }

由于 createRows 保存在状态挂钩中,它不会随着每次渲染而改变,也不会像我们想要的那样重新渲染 List

然而,这看起来更像是一种破解而不是解决方案。


将函数 prop 从功能组件发送到子组件的最佳实践是什么,而不会导致子组件不必要的重新渲染?

useCallback hook exists exactly to solve this problem. I advise you to carefully read the official guide to hooks,它几乎回答了所有可能的问题

  function Component(props) {
    const createRows = useCallback(() =>
      props.data.map(dataToRow);
    ), []); // provide dependencies here

    return <List createRows={createRows}/>;
  }

这就是useCallback的目的。您可以在下面我的一些相关回答中找到更多详细信息。