【问题标题】:Prevent re-render when sending function prop from functional component从功能组件发送功能道具时防止重新渲染
【发布时间】:2019-08-22 18:30:42
【问题描述】:

当向PureComponent 或功能组件发送道具时,您可以通过使用不会在每次渲染时更改的道具来优化性能,这将防止组件重新渲染。

当使用类组件时,这很简单:

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,所以prop 会发生变化,导致每次Component 重新渲染时都会重新渲染List。这可能会导致性能大幅下降。另请注意,createRows 不能放在功能组件之外,因为它依赖于 Listdata 属性。


现在,随着 Hooks 的介绍,可以将 createRows 保存在 useState 钩子中:

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

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

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

但是,这似乎更像是一种 hack 而不是解决方案。


在不导致子组件不必要的重新渲染的情况下,将功能道具从功能组件发送到子组件的最佳做法是什么?

【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    useCallback 钩子的存在正是为了解决这个问题。我建议你仔细阅读官方guide to hooks,它几乎回答了所有可能的问题

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

    【讨论】:

    • 如果孩子在调用回调时需要提供一些参数怎么办?那么我们必须使用useReducer 吗?很好奇为什么useCallback API 不允许传递任何参数...
    • 您可以为传递给useCallback 的函数指定所需的任何参数。您基本上可以在这里创建一个带有任意数量参数的自定义函数。只是在这种特殊情况下,我们不需要此回调函数的任何参数
    【解决方案2】:
    猜你喜欢
    • 1970-01-01
    • 2021-02-14
    • 2020-03-27
    • 2021-12-22
    • 2020-10-21
    • 2021-09-29
    • 2023-02-15
    • 2019-07-28
    • 1970-01-01
    相关资源
    最近更新 更多