5

When running the run function, I expect that value variable has value 'new', but since even 500 ms, it still remains 'old'. Why that happens and how coud this issue be solved?

import React, { Component, useState } from "react";
import { render } from "react-dom";

function App() {
  const [value, setValue] = useState('old');

  const run = async() => {
    setValue('new')
    const data = await wait(500)
    console.log(value)
  }

  return (
    <button onClick={run}>
      Run
    </button>
  );
}

render(<App />, document.getElementById("root"));

function wait(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}
Eugene Beliaev
  • 781
  • 1
  • 8
  • 15
  • Even if you are using a class component also if you access state suddenly you can't see the changes, if you need to see the data then you need to call the callback of this.setState, addition to this in promise setState behaves sync and in events it behaves async in React 17 they are trying to solve this issue by using concurrent mode. – Learner Dec 20 '19 at 05:14
  • 3
    I don't think this should be flagged as a duplicate. [useState set method not reflecting change immediately](https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately), which is regarding a _delayed_ state change. This question concerns a state that _never_ changes. All the answers are misunderstanding the question also. When you use _async_ notation, state cannot be viewed inside async function. It can however be updated. – Frederik Petersen Nov 24 '20 at 15:51
  • did you found the answer? – plsankar Mar 18 '21 at 13:28

3 Answers3

4

setState runs asynchronously so it is not immediately reflected in the function code block. You can try using useEffect to watch changes of your state.

useEffect(() => console.log('value', value), [value])

0

In your case const [value, setValue] = useState('old'); setValue is nothing but same like setState in class Components. So since setState and setValue is asynchronous functions, you can never predict when the values will get updated.

So either you can use componentDidUpdate in class components or useEffect like useEffect(() => callFn();, [value]) . so here callFn() is afunction which will be called after value has been updated.

hope it helps. feel free for doubts

Gaurav Roy
  • 11,175
  • 3
  • 24
  • 45
0

Ok, here is what I think is happenning: You click the button, which calls your run function - then the run function calls setState.

  • I think setState is supposed to cause a rerender of the component with the new value which would be shown immediately if you were displaying it somewhere. So if you want to see immediate changes, add a display.
  • When you console log in the run function immediately after setState, the component has not been rerendered which means you are still looking at the old value.
  • When the component rerenders, you are not seeing the console logged value because the run function has not been called again. Clicking the button twice should console log the new value because by then the component has rerendered with that new value.
jackthedev
  • 578
  • 5
  • 7