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

React多次重新渲染后网站卡顿问题求助:随机Div条生成场景下的性能排查

Hey Adam, let's break down your problem and fix it step by step!

1. Why the App Gets Laggy After 12+ Clicks

The core issue here is duplicate event listeners. Right now, you're running document.querySelector("#Reset").addEventListener directly in the top-level of your Bars component. That means every time the Bars component re-renders (which happens every time you call setBars), you're adding a new click listener to the Reset button.

After 12 clicks, you've got 12+ listeners all triggering setBars(getBars()) at the same time. This causes the component to re-render repeatedly, the DOM to update non-stop, and that's exactly why you're seeing severe lag.

Fix: Use useEffect to Bind Listeners Once

Wrap your event listener logic in a useEffect with an empty dependency array. This ensures the listener is only added once when the component mounts, and cleaned up when it unmounts:

function Bars() {
  const [bars, setBars] = React.useState(getBars());

  React.useEffect(() => {
    const resetBtn = document.querySelector("#Reset");
    const handleReset = () => setBars(getBars());
    
    resetBtn.addEventListener("click", handleReset);
    
    // Cleanup: remove listener when component unmounts to avoid memory leaks
    return () => resetBtn.removeEventListener("click", handleReset);
  }, []); // Empty array = run only on mount/unmount

  return (
    <div id="dataContainer">
      <div id="barContainer">
        {bars.map((height, index) => {
          // Important: Add a unique key for React to track elements efficiently
          return (
            <div key={index} className="sBar" style={{ height: `${height}px` }}></div>
          )
        })}
      </div>
      <h1>{bars.length} bars to sort</h1>
      <div id="btnContainer"><button id="btnSort">Sort</button></div>
    </div>
  )
}

Two quick extra fixes in the code above:

  • Use className instead of class in JSX (it's React's required syntax)
  • Add a key prop to the mapped divs—this helps React update the DOM efficiently instead of re-rendering everything from scratch
2. Is Separating Menu and Bars Components a Good Idea?

Absolutely! Separating components by responsibility is a core React best practice—your menu handles UI controls, and Bars handles rendering the visualization. That's a great design choice.

But instead of using DOM queries to connect the components (which leads to issues like your lag), use React's built-in data flow patterns. Here's how to do it properly:

Better Approach: Lift State to a Parent Component

Move the bars state and reset logic up to a parent component, then pass the necessary data/functions down via props:

// Parent component that orchestrates state and child components
function App() {
  const [bars, setBars] = React.useState(getBars());
  
  const handleReset = () => setBars(getBars());

  return (
    <div>
      {/* Pass the reset function to your Menu component */}
      <Menu onReset={handleReset} />
      {/* Pass the bars data to your Bars component */}
      <Bars bars={bars} />
    </div>
  )
}

// Menu component (now self-contained, no DOM queries needed)
function Menu({ onReset }) {
  return (
    <div>
      <button id="Reset" onClick={onReset}>Reset</button>
      {/* Add other menu items here */}
    </div>
  )
}

// Bars component (focused solely on rendering)
function Bars({ bars }) {
  return (
    <div id="dataContainer">
      <div id="barContainer">
        {bars.map((height, index) => (
          <div key={index} className="sBar" style={{ height: `${height}px` }}></div>
        ))}
      </div>
      <h1>{bars.length} bars to sort</h1>
      <div id="btnContainer"><button id="btnSort">Sort</button></div>
    </div>
  )
}

This approach has several benefits:

  • No more DOM manipulation hacks—everything follows React's predictable data flow
  • Components are decoupled and easier to test individually
  • You avoid the duplicate listener issue entirely, since the reset function is only defined once in the parent
Wrapping Up

The lag was caused by duplicate event listeners piling up with each render—fixing that with useEffect will immediately resolve the卡顿. And your component separation idea is solid; using props to connect components instead of DOM queries will make your code cleaner, more maintainable, and less prone to bugs.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 15:57:31