Petar
Petar

Reputation: 33

Why my sleep function doesn't make the React application freeze?

Why my sleep function doesn't make the React application freeze? Here's my code:

import React from "react";
import "./App.css";

function App() {
  const [count, setCount] = React.useState(0);
  (async () => {
    const sleep = async (miliseconds: number) => {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve("");
        }, miliseconds);
      });
    };
    await sleep(5000);
    console.log("hey");
  })();

  return (
    <div className="App">
      <h1>{count}</h1>
      <button onClick={() => setCount((count) => count + 1)}>+</button>
    </div>
  );
}

export default App;

So, I have an IIFE sleep function inside the component that is supposed to execute before every render. But when I click on the increment button of my counter, the DOM being updated immediately without waiting for my sleep function to finish its execution. What's wrong with it? If I use for loop to freeze the app everything works as expected but the sleep function implemented with promise doesn't cause my app freeze.

Upvotes: 1

Views: 629

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 371138

What this block of code does:

  (async () => {
    const sleep = async (miliseconds: number) => {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve("");
        }, miliseconds);
      });
    };
    await sleep(5000);
    console.log("hey");
  })();

is it creates a Promise that resolves after 5 seconds. That's it. The Promise isn't used anywhere, and so it isn't connected to anything in the rest of the code.

function App() {
  const [count, setCount] = React.useState(0);
  // here, create a Promise that resolves after 5 seconds, and don't do anything with it

  return (
    <div className="App">
      <h1>{count}</h1>
      <button onClick={() => setCount((count) => count + 1)}>+</button>
    </div>
  );
}

The App's return still executes immediately when App is called, so there's no delay before it renders.

If you wanted to add a render delay, conditionally render the component and set a state after 5 seconds.

function App() {
  const [count, setCount] = React.useState(0);
  const [render, setRender] = React.useState(false);
  React.useEffect(() => {
    setTimeout(() => {
      setRender(true);
    }, 5000);
  }, []);
  return !render ? null : (
    <div className="App">
      <h1>{count}</h1>
      <button onClick={() => setCount((count) => count + 1)}>+</button>
    </div>
  );
}

ReactDOM.createRoot(document.querySelector('.react')).render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div class='react'></div>

Upvotes: 3

Related Questions