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

为什么未关联的useState更新会触发react-window列表重新渲染

问题根因

你遇到的重渲染问题和react-window本身无关,是React组件渲染的基础规则导致的:

  • 你将Row组件定义在了App组件的函数体内部,每次App因为count状态更新触发重渲染时,函数体都会从头执行,Row组件每次都会生成一个全新的函数引用
  • FixedSizeList接收的children是新的Row实例, React会判定为需要重新渲染整个列表的可见节点,你加的React.memo完全不会生效:memo的作用是同一个组件前后渲染时对比props是否变化,现在组件本身的引用都变了,会直接走新组件的全量渲染流程,不会触发areEqual的对比逻辑
解决方案

方案1:将Row组件移出App组件外部(最推荐)

直接把Row的定义放在App组件外面,保证它的引用永远不会随App渲染变化:

import React, { useState  } from "react";
import { FixedSizeList, areEqual } from "react-window";

// 移到组件外部定义
const Row = React.memo(props => {
  const { index, style } = props;
  return <div style={style}>Row {index}</div>;
}, areEqual);

function App() {
  const [count, setCount] = useState(0);

  const handleOnClick = () => {
    console.log("PUSHED ME");
    setCount(count+1)
  }

  return (
    <div className="App">
      <FixedSizeList
        height={200}
        itemCount={100}
        itemSize={50}
        width={'100%'}
      >
        {Row}
      </FixedSizeList>
   
      <div onClick={handleOnClick}>点我</div>
    </div>
  );
}

export default App;

方案2:用useMemo缓存内部的Row组件

如果有特殊场景必须把Row定义在App内部,可以用useMemo缓存Row的引用,避免每次渲染生成新实例:

// App组件内部定义时添加缓存逻辑
const Row = useMemo(() => React.memo(props => {
  const { index, style } = props;
  return <div style={style}>Row {index}</div>;
}, areEqual), []);

如果你的Row需要用到App内部的状态,可以把相关状态通过props传递给Row,同时把对应状态加到useMemo的依赖数组里,areEqual会自动对比props变化,只有真的需要更新时才会重渲染对应行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 13:24:06