-1

I am using an async function with prevState. I am using prevState for a couple of purposes: 1) I am updating a deeply nested object 2) I am using current state to send data to an API. I am using async for the API call.

This is a simplified version of my code:

this.setState(async prevState => {
   //code using await to pull data from an Api

   return ({
      data: data
   })}, function(){
       //Here I do not see the updated state
       console.log(this.state)

   }
)

Without using async, it works fine, but then I cannot make use of await. How can I access my updated state from within the callBack function?

Further Details

Ultimately what I am trying to do is have three nested setState functions as follows. When a user page is saved the savePage() function will be triggered. In that function I want to:

  1. LOCK THE PAGE IN STATE: Add the page_id to a state array of locked pages. This will prevent further changes to the page.
  2. SEND DATA TO SERVER AND UPDATE STATE ON SUCCESS: In the callback I am then calling the Api to update the page. AND then update the page status as "saved" in the new setState
  3. UNLOCK THE PAGE: In the callback from the new setState function, I then issue a third setState function to remove the lock from the locked_pages array located in state. This probably can be combined with step 2.
kojow7
  • 10,308
  • 17
  • 80
  • 135
  • 1
    Why are you defining the callback function for `setState` to run as an `async` function? are you trying to make API calls inside of that callback? that would be the wrong approach for making api calls. If you `await` inside of this callback then yes you're going to mess up how setstate works. You need this function to be synchronous – John Ruddell Aug 28 '19 at 22:17
  • @JohnRuddell I have added further details to explain things more. – kojow7 Aug 28 '19 at 22:41
  • 1
    The `setState` function must return an object but an async function returns a `Promise`. – Emile Bergeron Aug 28 '19 at 22:43
  • [How to fetch data and put it in the state](https://reactjs.org/docs/faq-ajax.html) – Emile Bergeron Aug 28 '19 at 22:45
  • For subsequent setState calls, use the second parameter. `this.setState({/**/}, () => this.fetchOtherThing(this.state.data))` – Emile Bergeron Aug 28 '19 at 22:48
  • You could also ["promisify" `setState`](https://stackoverflow.com/q/53409325/1218980) and it would then be possible to `await this.promiseSetState(/**/)` – Emile Bergeron Aug 28 '19 at 22:52
  • The problem is that I need to use a prevState value to pass to the API, but I cannot get a prevState value unless I am in the setState function. However, it is a catch-22 situation, because I cannot call the API unless I do it asynchronously. – kojow7 Aug 28 '19 at 23:03
  • 1
    `prevState` is the same thing as `this.state` before you call `setState`. So just do your api request before setting state. Then setState with the results or whatever you need to do... aka `const { value } = this.state; this.setState( prevState => { prevState.value === value // true ...` – John Ruddell Aug 28 '19 at 23:08
  • I was of the understanding that setState is done in batch, and there could be other setStates waiting in queue that might change the value of the state. So if I access this.state and pass the value to my API there is a chance that I could be accessing a slightly older version of state and thus sending the API the incorrect value. Am I wrong about this? If so, what am I misunderstanding? – kojow7 Aug 29 '19 at 04:01
  • the only time that would happen is if you are calling setstate multiple times within like a second. Just dont do that. you're controlling when setState is called. If you need help understanding more I'd be happy to review code for you and give pointers. – John Ruddell Aug 29 '19 at 16:57

1 Answers1

0

I don't have much to work with.

But I would suggest you to put setState inside componentDidMount()

and use PromiseResult.then(data=>this.setState(data))