react-window 列表项高度动态变化时怎么处理?

Top丶静怡 阅读 4

我用 react-window 的 FixedSizeList 渲染一个消息列表,但每条消息内容长度不一,有的带图片有的纯文本,导致实际高度不一样。强行用固定 height 会出现重叠或留白,试过改用 VariableSizeList,但性能好像变差了,而且滚动有点卡顿,是不是我用法有问题?

这是我的简化代码:

const Row = ({ index, style }) => (
  <div style={style} className="message-item">
    {messages[index].content}
  </div>
);

<VariableSizeList
  height={500}
  itemCount={messages.length}
  itemSize={() => 60} // 这里其实不知道具体高度
  width="100%"
>
  {Row}
</VariableSizeList>
我来解答 赞 4 收藏
二维码
手机扫码查看
1 条解答
世梅(打工版)
问题在于你的 itemSize 根本没动态计算,每次都返回 60。VariableSizeList 需要知道每个 item 的精确高度才能正常工作。

懒人方案:用 ref 缓存高度,第一次渲染时测量,之后用缓存。

const [heights, setHeights] = useState({});
const itemSize = (index) => heights[index] || 100; // 默认值

const Row = ({ index, style, data, measure }) => {
const ref = useRef(null);

useEffect(() => {
if (ref.current && !heights[index]) {
setHeights(prev => ({ ...prev, [index]: ref.current.offsetHeight }));
}
}, []);

return (
<div style={style} ref={ref} className="message-item">
{data[index].content}
</div>
);
};

// 记得传 messages 作为 itemData
<VariableSizeList
height={500}
itemCount={messages.length}
itemSize={itemSize}
width="100%"
itemData={messages}
>
{Row}
</VariableSizeList>


这样只有第一次渲染会触发测量,后续滚动直接从缓存读,性能就好了。
点赞
2026-03-14 14:00