const onSelect = useCallback(id => setActive(id), []);
export default React.memo(Row);

打开 Profiler 每次父级输入都重渲染整张长列表,子组件套了 React.memo 照样闪,控制台没有报错,火焰图里每个 Row 都在重画。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。

原因不复杂,父级每次渲染都新建对象和内联函数传给子组件,props 浅比较永远不相等,memo 直接失效,包了等于没包,还多一层比较开销,长列表最容易看出来。

「memo 失效」确认了原因之后,改动尽量只碰那一处,顺手改的东西后面最容易出问题。改完隔一天再看一次,当场正常不代表能稳住。

测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。

处理上按这个顺序:回调统一用 useCallback 把引用固定住,别写成内联箭头函数;传给子组件的对象用 useMemo 缓存起来,别在 JSX 里新建;实在必要时再给 memo 写自定义比较函数。

改完只确认一件事:Profiler 里输入时只有当前行重渲染,其他行保持灰色,不再全量刷新,输入也跟手。

作者 9823189