Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React setState with promise as a callback [duplicate]

I received an error when trying to SetState using a Promise as a callback in React. This is likely due to an error on my part and would like some clarification on set State in React. The error message I am receiving is as follows.

ERR: "Invalid argument passed as callback. Expected a function. Instead received: [object Promise]"

I have refactored my code example below (edit) to try and provide use to others.

    this.setState({ value: v }, this.callAsync)

// Async function 

  callAsync = async () => {
    await this.props.foo({
    // Something async-y
   })
 .then(success => console.log(success)
 }
like image 236
o1n3n21 Avatar asked Dec 31 '17 17:12

o1n3n21


1 Answers

Re the code in your original question:

this.setState({ value: v }, this.callAsync())

An async function always returns a promise, which isn't (of course) a callback. In your case, that promise resolves with undefined as you haven't done a return in your callAsync.

If your goal is to call callAsync after the state update is complete, then wrap the call in another function, e.g.:

this.setState({value: v}, async () => {
    try {
        await this.callAsync();
    } catch (e) {
        // handle error
    }
});

or

this.setState({value: v}, () => {
    this.callAsync().catch(e => {
        // handle error
    });
});

Note that it's essential to handle potential errors; otherwise, you'll get unhandled resolution errors if the promise returned by this.props.foo is rejected.


Re the code in your modified question:

This is just a simple case of this not being what you expect in the callback, as described in detail in this question's answers. The solution above also works for that, conveniently; it's one of the solutions listed by the answers there. And it handles errors correctly, which some of the other answers to that question (using this.callAsync.bind(this) for instance) won't.

like image 192
T.J. Crowder Avatar answered Oct 29 '22 09:10

T.J. Crowder