
React 18 中因并发渲染和事件委托机制变更,原生 onScroll 在包裹 react-virtualized 组件的容器上可能不触发;需改用组件内置的 onScroll 回调或通过 ref + addEventListener 手动绑定滚动事件。
react 18 升级后因并发渲染和事件委托机制变更,原生 `onscroll` 在包裹 `react-virtualized` 组件的容器上可能不触发;需改用组件内置的 `onscroll` 回调或通过 ref + `addeventlistener` 手动绑定滚动事件。
在 React 18 中,onScroll 事件默认不再冒泡至非滚动容器(如外层
✅ 推荐方案:优先使用组件原生 onScroll 回调
react-virtualized 的 List、MultiGrid 等组件均暴露 onScroll prop,它接收 { scrollLeft, scrollTop, clientWidth, clientHeight } 对象,语义清晰且与 React 18 完全兼容:
React 与 Next.js 性能优化指南,源自 Vercel 工程团队。适用于编写、审查或重构 React/Next.js 代码时使用。
import { List } from 'react-virtualized';
const TableComponent = ({ scrollHandler, getRow, rowCount, rowHeight }) => {
return (
<autosizer>
{({ width, height }) => (
<list width="{width}" height="{height}" rowcount="{rowCount}" rowheight="{rowHeight}" rowrenderer="{getRow}" list onscroll scrollleft scrolltop> {
scrollHandler({ scrollLeft, scrollTop });
}}
// 避免在外层 div 上设置 onScroll
/>
)}
</list></autosizer>
);
};
⚠️ 替代方案:Ref + 原生事件监听(适用于无内置回调的场景)
若所用组件未暴露 onScroll(如自定义封装),可通过 useRef 获取滚动容器 DOM 并手动绑定:
import { useEffect, useRef } from 'react';
import { List } from 'react-virtualized';
const TableComponent = ({ scrollHandler, getRow, rowCount, rowHeight }) => {
const listRef = useRef(null);
useEffect(() => {
const node = listRef.current?.getDOMNode?.(); // react-virtualized v9+ 推荐方式
if (node) {
const handleScroll = () => {
scrollHandler({
scrollLeft: node.scrollLeft,
scrollTop: node.scrollTop,
});
};
node.addEventListener('scroll', handleScroll, { passive: true });
return () => node.removeEventListener('scroll', handleScroll);
}
}, [scrollHandler]);
return (
<autosizer>
{({ width, height }) => (
<list ref="{listRef}" list width="{width}" height="{height}" rowcount="{rowCount}" rowheight="{rowHeight}" rowrenderer="{getRow}"></list>
)}
</autosizer>
);
};
? 关键注意事项:
- 不要依赖 AutoSizer 或外层 div 的 onScroll —— 它们通常不是实际滚动容器;
- react-virtualized@9.13.0 中,List/MultiGrid 的滚动容器是内部生成的 .ReactVirtualized__List 或 .ReactVirtualized__Grid 元素,需通过 ref.current.getDOMNode() 访问;
- 使用 passive: true 提升滚动性能(尤其移动端);
- 若使用 StrictMode(React 18 默认启用),确保 useEffect 清理逻辑正确,避免重复绑定/内存泄漏。
总结:升级 React 18 后,onScroll 失效本质是事件委托层级变化所致。最佳实践是弃用外层容器监听,转而采用组件官方支持的 onScroll 回调——既兼容性强,又无需手动管理 DOM 和生命周期,代码更健壮、可维护性更高。










