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

React 18虚拟表格滚动弹跳求助(React 17渲染正常)

React 18虚拟数据网格滚动弹跳问题求助

我开发了一个基于transform: translateY实现滚动偏移的虚拟数据网格,该功能在React 17中运行正常,但迁移到React 18后出现了滚动弹跳的异常问题。仅通过切换ReactDOM的导入方式(React 17使用已弃用的react-dom,React 18使用react-dom/client)即可复现该问题。我已尝试设置overscroll-behaviour: none但无效,耗时1.5天仍未找到原因,恳请帮忙解决。

效果对比

React 18效果(滚动弹跳)

React 18滚动弹跳

React 17效果(正常滚动)

React 17正常滚动

最小复现代码

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Virtuailsed table</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

index.js

// import ReactDOM from "react-dom";
import ReactDOM from "react-dom/client";
import { useState } from "react";
import "./styles.css";

let vendors = [];

for (let i = 0; i < 1000; i++ ){
  vendors.push({
    id: i,
    edrpou: i,
    fullName: i,
    address: i
  })
}

const scrollDefaults = {
  scrollTop: 0,
  firstNode: 0,
  lastNode: 70,
};

function App() {
  const [scroll, setScroll] = useState(scrollDefaults);
  const rowHeight = 20;
  const tableHeight = rowHeight * vendors.length + 40;
  const handleScroll = (event) => {
    const scrollTop = event.currentTarget.scrollTop;
    const firstNode = Math.floor(scrollTop / rowHeight);
    setScroll({
      scrollTop: scrollTop,
      firstNode: firstNode,
      lastNode: firstNode + 70,
    });
  };
  const vendorKeys = Object.keys(vendors[0]);
  return (
    <div
      style={{ height: "1500px",  overflow: "auto" }}
      onScroll={handleScroll}
    >
      <div className="table-fixed-head" style={{ height: `${tableHeight}px` }}>
        <table style={{transform: `translateY(${scroll.scrollTop}px)`}}>
          <thead style={{ position: "relative" }}>
            <tr>
              {vendorKeys.map((key) => <td>{key}</td>)}
            </tr>
          </thead>
          <tbody >
            {vendors.slice(scroll.firstNode, scroll.lastNode).map((item) => (
              <tr style={{ height: rowHeight }} key={item.id}>
                {vendorKeys.map((key) => <td><div className="data">{item[key]}</div></td>)}
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// const rootElement = document.getElementById("root");
// ReactDOM.render(<App />, rootElement);

const root = ReactDOM.createRoot(
  document.getElementById('root')
);

root.render(
  <App />
);

styles.css

* {
  padding: 0; 
  margin: 0
}
.table-fixed-head thead th{
  background-color: white;
}
.row {
  line-height: 20px;
  background: #dafff5;
  max-width: 200px;
  margin: 0 auto;
  box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.5);
}
.data{
  width: 150px;
  white-space: nowrap;
  overflow: hidden;
  margin-right: 20px;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 05:18:09