Home > OS >  How do I update the state of a variable with a wait time using promise inside React functional compo
How do I update the state of a variable with a wait time using promise inside React functional compo

Time:07-23

I have the following code and my goal is to update the value of text on the button click after 2 seconds. While the console log is taking 2 seconds to print, the text value is being updated right away. How can I make it to wait for 2 seconds to update the text value?

function App() {
    const [text, setText] = React.useState('Initial state');

    const myPromise = new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('Changed state');
            resolve('Changed state');
        , 2000);
    });

    const handleOnClick = () => {
        myPromise
        .then(res => setText(res))
        .catch(e => console.log(e));
    };

    return (
        <p>{text}</p>
        <button onClick={handleOnClick}>Click Me!</button>
    );
}

CodePudding user response:

This happens because of the following:

  1. Your App component initially renders.
  2. mypromise Promise object gets initialized and therefore triggers its timeout.
  3. When you press the button, 2000ms have already gone (from the render time) and therefore the mypromise has already resolved.
  4. Your then function is immediately applied and calls setText.
  5. setText forces your component to re-render.
  6. So the App function re-runs, and the mypromise object re-initializes forcing the setTimeout to re-trigger.

A way to fix it is to make your promise run lazily:

  ...
  const myPromise = () =>
    new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log("Changed state");
        resolve("Changed state");
      }, 2000);
    });

  const handleOnClick = () => {
    myPromise()
      .then((res) => setText(res))
      .catch((e) => console.log(e));
  };
  ...

CodePudding user response:

export default function App() {
  const [text, setText] = useState("Initial text");

  const awaitPromise = (ms) => {
    return new Promise((resolve) => setTimeout(resolve, ms));
  };

  const handleClick = async () => {
    await awaitPromise(2000);
    setText("Something else");
  };

  return (
    <div className="App">
      {text}
      <button onClick={handleClick}>Click</button>
    </div>
  );
}
  • Related