简体   繁体   中英

is the DOM updated after each change + render

I'm trying to fully understand the relations among DOM reconciliation, virtual DOM, component rendering and effect hook. I'm using the following code, which returns a status of "three". But are the intermediate statuses "one" and "two" always printed on the DOM, even for a blinky fraction of a second?

export default function App() {
  const [status, setStatus] = React.useState("zero");

  const handleChangeStatus = () => {
    setStatus("one");
  };

  useEffect(() => {
    if (status === "one") {
      setStatus("two");
    }
  }, [status]);

  useEffect(() => {
    if (status === "two") {
      setStatus("three");
    }
  }, [status]);

  return (
    <div>
      <div id={status}>{status}</div>
      <br />
      <button onClick={handleChangeStatus}>Change statuses</button>
    </div>
  );
}

once clicked,

Simply put, the useEffect hook runs at the end of the render cycle after content has been flushed to the DOM. Each useEffect hook runs each render cycle in the order they are declared. Each useEffect hook enqueues a state update on a different render cycle based on the dependency's value in the effect callback.

But are the intermediate statuses "one" and "two" always printed on the DOM, even for a blinky fraction of a second?

Yes, they are. Each state update is enqueued in a different render cycle, so each update will be processed and the reconciled diff flushed to the DOM and rendered. The React framework aims for about a 60fps refresh rate, or, about 17ms per render cycle. The basic math: 1s/60render * 1000ms/1s = 1000ms/60render = 16.6667ms/render. 17ms is nearly imperceptible I dare say.

If you take this into account and multiply by the 3 triggered state updates, we're talking about around 50ms for just React doing the work. That's still nearly imperceptible. For reference, it seems the average time for a human to blink is between 100-150ms .

You can also very easily test this out for yourself with a couple extra useEffect hooks logging out the state updates and render cycles. Take note of the timestamps in the log output.

 function App() { const [status, setStatus] = React.useState("zero"); const handleChangeStatus = () => { setStatus("one"); }; React.useEffect(() => { if (status === "one") { setStatus("two"); } }, [status]); React.useEffect(() => { if (status === "two") { setStatus("three"); } }, [status]); React.useEffect(() => { console.log("Status updated", status); }, [status]); React.useEffect(() => { console.log("Component rendered") }) return ( <div> <div id={status}>{status}</div> <button onClick={handleChangeStatus}>Change statuses</button> </div> ); } const rootElement = document.getElementById("root"); const root = ReactDOM.createRoot(rootElement); root.render( <React.StrictMode> <App /> </React.StrictMode> );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script> <div id="root" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM