首页 > 解决方案 > React 通过使用 useState 的功能变体来防止重新渲染

问题描述

我试图了解在使用普通 setState V/s 的另一种情况下使用功能状态更新的情况下如何导致功能组件重新渲染的确切差异

相关代码片段如下

案例 1:导致组件重新渲染

const onRemove = useCallback(
  tickerToRemove => {
    setWatchlist(watchlist.filter(ticker => ticker !== tickerToRemove));
  },
  [watchlist]
);

案例2:不会导致重新渲染

const onRemove = useCallback(tickerToRemove => {
  setWatchlist(watchlist =>
    watchlist.filter(ticker => ticker !== tickerToRemove)
  );
}, []);

可以看到这两个用例的完整示例;

https://codesandbox.io/s/06c-usecallback-final-no-rerenders-bsm64?file=/src/watchlistComponent.js

https://codesandbox.io/s/06b-usecallback-usememo-ngwev?file=/src/watchlistComponent.js:961-970

更新

全文链接 https://medium.com/@guptagaruda/react-hooks-understanding-component-re-renders-9708ddee9928#204b

对于如何防止子组件的重新渲染,我有点困惑。

在文章中它说

“谢天谢地,来自 useState 钩子的 setter 函数支持一个功能变体,它可以帮助我们。我们可以发送一个获取当前状态作为参数的函数,而不是使用更新的监视列表数组调用 setWatchlist 。”

但是,我有点困惑是否因为我们使用空数组(因为 [] 在渲染之间没有变化)而阻止了子组件的重新渲染,V/s 因为使用了 useState hook 的 setter 变体而被阻止了?

标签: javascriptreactjsreact-hooksuse-stateusecallback

解决方案


是否使用功能状态更新与您所问的问题无关。您似乎在问为什么(1)具有依赖关系的回调会触发重新渲染,而(2)具有空依赖关系的回调。

答案非常简单。在版本 (2) 中,您提供了从组件挂载时起就不会更改的稳定回调引用,而在 (1) 中,回调引用在依赖项发生更改时发生更改。请记住,当 state 或props更新(新的回调引用是新的 prop 引用父组件重新渲染时,React 组件会重新渲染。由于onRemove道具在 (1) 中更新,因此会触发重新渲染。


推荐阅读