You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中useState函数式更新与useCallback结合避免重渲染原理解疑

两种写法的重渲染差异核心逻辑

阻止子组件重渲染是 useCallback 空依赖数组 + useState 函数式更新共同作用的结果,二者缺一不可。

情况1会触发重渲染的原因

第一种写法的代码如下:

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

这里 useCallback 的依赖数组包含状态 watchlist:

  • 每次 watchlist 发生变更时,useCallback 都会生成一个全新的 onRemove 函数引用
  • 只要这个函数作为 props 传给子组件,哪怕子组件用 React.memo 包裹,props 引用变化也会触发子组件重渲染
  • 这种写法不能把 watchlist 移出依赖数组:如果移出会触发闭包陷阱,onRemove 拿到的永远是第一次渲染的旧 watchlist 值,过滤逻辑会直接出错。

情况2可以避免重渲染的原因

第二种写法的代码如下:

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

这里函数式更新的作用是让状态更新逻辑不依赖外层作用域的状态值:

  • 传给 setWatchlist 的回调函数,接收的参数是 React 内部保证的最新 watchlist 状态,不需要从外层作用域获取,因此 onRemove 的执行逻辑完全不依赖外部的 watchlist 变量
  • 因此可以给 useCallback 传入空依赖数组,这样 onRemove 的函数引用从组件首次挂载后就永远不会变化
  • 不变的 props 传给 React.memo 包裹的子组件,就不会触发不必要的子组件重渲染。

二者缺一不可的验证

  • 只使用函数式 setter 但没有给 useCallback 正确设置空依赖:函数引用还是会随依赖变化,子组件依旧会重渲染
  • 只给 useCallback 设置空依赖但不使用函数式 setter:会触发闭包陷阱,拿到的状态永远是旧值,业务逻辑直接出错,谈不上重渲染优化。

内容的提问来源于stack exchange,提问作者copenndthagen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 14:09:04