0

My component is built like this:

function myComponent(props){
  const [state, setState] = useState("WAIT")
  function run(){
    setState("LOAD");
    props.apiFetch();
    setState("WAIT");
  }
  return(<h1 onClick={run}>{status}</h1>)
}

When I click on the element, state is displayed as WAIT the whole time, but never as LOAD. I'd appreciate any feedback.

EDIT: Changing my function to

async function run(){
 await setState("LOAD")
 ...
}

does not help

Sven
  • 1,014
  • 1
  • 11
  • 27
  • 1
    Possibly related to https://stackoverflow.com/questions/36085726/why-is-setstate-in-reactjs-async-instead-of-sync? – Miss Skooter Mar 03 '23 at 15:39
  • Note: component names must be in PascalCase, not camelCase. – Andy Mar 03 '23 at 15:40
  • @MissSkooter It is very much related, thx, but it does not explain how to fix it in my case, it does explain the other viewpoint, what to do if you don't want to wait for updated state. – Sven Mar 03 '23 at 15:42
  • 1
    hi, this is a classic "why does my asynchronous javascript not execute synchronously" question. https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call might be a good read to start with – kvetis Mar 03 '23 at 15:45
  • There are [~2.6 million different tutorials on this topic](https://www.google.com/search?q=how+to+fetch+and+render+api+data+react&oq=how+to+fetch+and+render+api+data+react&aqs=chrome..69i57j33i22i29i30.9092j0j7&sourceid=chrome&ie=UTF-8). – Jared Smith Mar 03 '23 at 15:59

1 Answers1

5

All of the suggested references in the comments help explain what's happening here. But here's a simple explanation of what's happening to help you out (before this gets duped and removed):

function myComponent(props){
  const [state, setState] = useState("WAIT")
  function run(){
    setState("LOAD");
    // Yes, state is set to LOAD, albeit briefly.

    props.apiFetch();
    // fetch is an async api, and therefore non-blocking, i.e the next line of code runs immediately.

    setState("WAIT");
    // This runs immediately after the first setState, so you never actually see the state being set to LOAD. It just gets set right back to WAIT because Javascript doesn't wait for fetch to finish before moving on.

  }
  return(<h1 onClick={run}>{state}</h1>)
}

As a side note, you would need to apply the await to the props.apiFetch() to get the effect you're looking for, not the setState call. Although, depending on the speed of the fetch return, you still may not see the state changing on screen.

silencedogood
  • 3,209
  • 1
  • 11
  • 36