Event Loop and React

Blocking the Thread Freezes the UI

Example

While a long synchronous loop runs, the browser cannot paint or handle clicks. Press "Block for 2s" and try to click the counter: it reacts only after the loop ends. Splitting work with setTimeout lets the event loop breathe.

import { useState } from 'react';

export default function App() {
  const [count, setCount] = useState(0);
  const [status, setStatus] = useState('idle');

  const block = () => {
    const end = Date.now() + 2000;
    while (Date.now() < end) {}     // freezes everything
    setStatus('blocking work done');
  };
  const chunked = () => {
    let i = 0;
    setStatus('working in chunks...');
    const step = () => {
      const end = Date.now() + 50;
      while (Date.now() < end) {}   // 50 ms of work
      if (++i < 40) setTimeout(step, 0); else setStatus('chunked work done');
    };
    setTimeout(step, 0);
  };
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Counter: {count}</button>
      <p>
        <button onClick={block}>Block for 2s</button>
        <button onClick={chunked}>Same work in chunks</button>
      </p>
      <p>Status: {status}</p>
    </div>
  );
}

Result

What React Does

  • Automatic batching (React 18): several setState calls in the same event, timeout or promise are combined into one re-render.
  • Concurrent rendering: React renders in small units and yields to the browser so typing stays smooth (useTransition).
  • Move really heavy work (parsing, image processing) to a Web Worker.