Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Does React re-render more than once per onClick Event?

Im reading the learning react documentation on the react website and in the Queueing A Series of State Updates section there is a sentence that reads
"the UI won’t be updated until after your event handles, and any code in it, completes." From this I get the impression that there can only be one render
per onClick event but in running the following component it seems the component re-renders twice. Once when adding to the pending state and another when decrementing the pending state and incrementing state inside the setTimeout function.

function RequestTracker() {
  const [pending, setPending] = useState(0);
  const [completed, setCompleted] = useState(0);
  useEffect(() => {
    console.log("MyComponent rendered!");
  });

  function handleClick() {
    setPending((p) => p + 1);
    setTimeout(() => {
      setCompleted((c) => c + 1);
      setPending((p) => p - 1);
    }, 3000);
  }

  return (
    <>
      <h3>Pending: {pending}</h3>
      <h3>Completed: {completed}</h3>
      <button onClick={handleClick}>Buy</button>
    </>
  );
}

Doesn’t this contradict the statement that React only renders the UI after the event handler completes all code in it?

Using the useEffect there is indeed more than one render per click. How should I think about
how React queues and executes re-renders. Thank you!

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

the UI won’t be updated until after your event handles, and any code in it, completes.

This statement is true. Your handleClick function is completing before the component re-renders.

but in running the following component it seems the component re-renders twice

That’s to be expected in this case. Look closely at what the code is doing:

function handleClick() {
  setPending((p) => p + 1);
  setTimeout(() => {
    setCompleted((c) => c + 1);
    setPending((p) => p - 1);
  }, 3000);
}

What does the function handleClick do? Exactly two things:

  1. Call setPending to queue a state update.
  2. Call setTimeout to schedule some function to execute at some later time.

Then it’s done. The function has run to completion, performed all of its tasks, and the framework now sees that a state update has been queued and the framework re-renders the component with the new state.

Then, at some later time, this happens:

setCompleted((c) => c + 1);
setPending((p) => p - 1);

Which does exactly two things:

  1. Call setCompleted to queue a state update.
  2. Call setPending to queue a state update.

Once this is done, this operation has completed its logic. The React framework then sees that there are state updates, processes them, and re-renders the component accordingly.


Overall it seems that your confusion is from an expectation that setTimeout is a blocking operation. It isn’t. It schedules logic to happen at some later time, and then frees up the JavaScript engine to continue processing.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading