将道具发送到PureComponent
或功能组件时,您可以使用每次渲染都不会更改的道具来优化性能,这将阻止组件重新渲染。
使用类组件时,这很简单:
class Component extends React.Component {
render() {
return <List createRows={this.createRows}/>;
}
createRows = () => this.props.data.map(dataToRow);
}
鉴于List
是PureCompoment
或功能组件,createRows
道具永远不会导致List
的重新渲染。
但是,如果Component
是功能组件,则不再可能:
function Component(props) {
return <List createRows={createRows}/>;
function createRows() {
return props.data.map(dataToRow);
}
}
由于每次渲染时都会创建createRows
Component
因此道具会发生变化,导致每次重新渲染Component
时都会重新渲染List
。这可能会导致性能大幅下降。另请注意,createRows
不能放置在功能组件之外,因为它依赖于List
的data
道具。
现在,随着 Hooks 的介绍,可以将createRows
放在useState
钩中:
function Component(props) {
const [ createRows ] = useState(() => () =>
props.data.map(dataToRow);
);
return <List createRows={createRows}/>;
}
由于createRows
保存在状态钩子中,因此它不会随每次渲染而更改,并且不会像我们想要的那样重新渲染List
。
但是,这似乎更像是一种黑客攻击,而不是解决方案。
将函数道具从功能组件发送到子组件而不会导致子组件不必要的重新渲染的最佳实践是什么?
>useCallback
钩子的存在正是为了解决这个问题。我建议您仔细阅读钩子的官方指南,它几乎回答了所有可能的问题
function Component(props) {
const createRows = useCallback(() =>
props.data.map(dataToRow);
), []); // provide dependencies here
return <List createRows={createRows}/>;
}
这就是useCallback
的目的。您可以在下面的一些相关答案中找到更多详细信息。
React Hooks 使用回调的简单示例的问题
使用 React 的 useCallback 钩子代替 useEffect 的意图是什么?
React Hooks useCallback 导致子项重新渲染