电脑课堂
柔彩主题三 · 更轻盈的阅读体验

频繁setState导致卡顿?可能是这些地方没处理好

发布时间:2026-01-10 10:10:32 阅读:15 次

页面卡顿不一定是网络问题

最近有朋友跟我吐槽,说他做的后台管理页面,点个按钮要等两三秒才有反应。一开始以为是接口慢,结果查了 network 面板发现数据早就回来了。问题出在哪儿?最后定位到是 setState 调得太勤快。

React 里 setState 看着简单,但用得不当,页面立马变“老年机”。

为什么 setState 多了就卡

每次调 setState,React 就会标记组件需要更新,然后进入重新渲染流程。如果一秒内触发几十次,浏览器就得忙死:虚拟 DOM 对比、DOM 更新、重排重绘全来一遍。用户的操作反而被晾在一边,自然就卡了。

比如有个计数器功能,想实现每按一次加一,结果写成了这样:

for (let i = 0; i < 100; i++) {
this.setState({ count: this.state.count + 1 });
}

这一下就触发了 100 次更新,页面不卡才怪。

异步事件里也容易踩坑

再比如监听鼠标移动,有人直接拿 setState 记坐标:

handleMouseMove = (e) => {
this.setState({ x: e.clientX, y: e.clientY });
};

鼠标一划,几十次事件打过来,setState 跟不要钱似的。其实用户根本看不出这么细的变动,多数都是白算。

怎么解决才靠谱

批量更新是个办法。React 在事件回调里本来就会自动批处理 setState,但如果是 setTimeout 或原生事件,就得自己控制。比如鼠标移动的例子,可以节流一下:

import _ from 'lodash';

constructor() {
super();
this.handleMouseMove = _.throttle(this.updatePosition, 50);
}

updatePosition = (e) => {
this.setState({ x: e.clientX, y: e.clientY });
};

这样一秒钟最多更新 20 次,体验够用,性能也扛得住。

函数式 setState 减少无效更新

如果新状态依赖旧状态,别用 this.state 直接算,用函数形式:

this.setState((prevState) => ({
count: prevState.count + 1
}));

这样即使多次调用,也能保证结果正确,避免因状态延迟导致的重复计算和多余渲染。

该用 useRef 的时候别硬上 setState

有些数据变了不需要界面刷新,比如存个定时器 id 或临时标记。这时候往 state 里塞,纯粹是给 React 找活干。换成 useRef 存,改值不触发更新,干净利落。

卡顿问题很多时候不是框架不行,而是用法太直白。把 setState 当普通变量赋值用,迟早出事。多想想“这次更新真有必要吗”,页面顺滑不少。