pallendes
pallendes

Reputation: 95

Best way to handle async actions from container components

I have two async actions that I have to be sure that they were executed correctly before to continue with the next block of code.

The code looks like this:

createUser = () => {
    let user = this.state.user
    //create user session (this is a async action - thunk)
    //What is the correct way to wait until this method is executed?
    this.props.createSession(user)
    //if session exists means it was created
    if(this.props.session.session) {
      //What is the correct way to wait until this method is executed?
      this.props.createUser(user) //another async action
      if(this.props.userReducer.currentUser) {
        ToastAndroid.show('User registered successfully!', ToastAndroid.SHORT)
        this.props.goTo('productsContainer') //transition to the next scene
      }
    } else {
      ToastAndroid.show(this.props.session.err, ToastAndroid.SHORT)
    }
}

Because the method createSession() and createUser() are async actions I'm a little bit lost about how to "wait" until the first one and the second one are executed.

Maybe it is a dumb question but I'm a newbie at the react-redux world.

Upvotes: 0

Views: 180

Answers (1)

Stefan Dragnev
Stefan Dragnev

Reputation: 14473

Given that the actions are async, they return promises. So, wait on the promises:

createUser = () => {
    let user = this.state.user
    //create user session (this is a async action - thunk)
    //What is the correct way to wait until this method is executed?
    this.props.createSession(user)
        .then(() => {
            //if session exists means it was created
            if(this.props.session.session) {
              //What is the correct way to wait until this method is executed?
              this.props.createUser(user) //another async action
              if(this.props.userReducer.currentUser) {
                ToastAndroid.show('User registered successfully!', ToastAndroid.SHORT)
                this.props.goTo('productsContainer') //transition to the next scene
              }
            } else {
              ToastAndroid.show(this.props.session.err, ToastAndroid.SHORT)
            }
        })
}

And so on.

If you're using Babel or TypeScript, you can also use the async/await syntax:

createUser = async function() {
    let user = this.state.user
    //create user session (this is a async action - thunk)
    //What is the correct way to wait until this method is executed?
    await this.props.createSession(user)
    //if session exists means it was created
    if(this.props.session.session) {
      //What is the correct way to wait until this method is executed?
      await this.props.createUser(user) //another async action
      if(this.props.userReducer.currentUser) {
        ToastAndroid.show('User registered successfully!', ToastAndroid.SHORT)
        this.props.goTo('productsContainer') //transition to the next scene
      }
    } else {
      ToastAndroid.show(this.props.session.err, ToastAndroid.SHORT)
    }
}.bind(this)

Given, however that the entire method works only through data passed in props (with the exception of state.user), which seem to come from the store anyway, it makes more sense to turn the whole method into an action:

createUser = () => props.createSessionAndUser(this.state.user)
...
// implement entire logic in createSessionAndUser action

Upvotes: 1

Related Questions