Using async setState

孤街浪徒 提交于 2019-11-27 05:16:55

问题


I have function which dispatched an action. I would like to display a loader before and after the action. I know that react composing the object passed to setState. the question is how can I update the property in async way:

handleChange(input) {
    this.setState({ load: true })
    this.props.actions.getItemsFromThirtParty(input)
    this.setState({ load: false })
}

Basically, it all worked great if I put this property as part of the application state (using Redux), but I really prefer to bring this property to the component-state only.


回答1:


Wrap the rest of your code in the callback of the first setState:

handleChange(input) {
  this.setState({
    load: true
  }, () => {
    this.props.actions.getItemsFromThirtParty(input)
    this.setState({ load: false })
  })
}

With this, your load is guaranteed to be set to true before getItemsFromThirtParty is called and the load is set back to false.

This assumes your getItemsFromThirtParty function is synchronous. If it isn't, turn it into a promise and then call the final setState within a chained then() method:

handleChange(input) {
  this.setState({
    load: true
  }, () => {
    this.props.actions.getItemsFromThirtParty(input)
      .then(() => {
        this.setState({ load: false })
      })
  })
}



回答2:


you can wrap the setState in a Promise and use async/await as below

setStateAsync(state) {
    return new Promise((resolve) => {
      this.setState(state, resolve)
    });
}

async handleChange(input) {
    await this.setStateAsync({ load: true });
    this.props.actions.getItemsFromThirtParty(input);
    await this.setStateAsync({ load: false })
}

Source: ASYNC AWAIT With REACT




回答3:


Here's what you can do...

  1. Change your action to take in a onFetchComplete callback, along with the input.
  2. Change your handleChange to -

    handleChange(input) {
        this.setState({ load: true }, ()=>
            this.props.actions.getItemsFromThirtParty(input,
            ()=>this.setState({ load: false }))
        );
    }
    

This will ensure the action processor code can invoke back your state change callback even if it's not written in a promise based fashion.




回答4:


Here's a typescript implementation of an "async-await" setState:

async function setStateAsync<P, S, K extends keyof S>(
  component: Component<P, S>,
  state:
    ((prevState: Readonly<S>, props: Readonly<P>) => (Pick<S, K> | S | null)) |
    Pick<S, K> |
    S |
    null
) {
  return new Promise(resolve => component.setState(state, resolve));
}



回答5:


A small update- using promises for the action creators and async/await works great, and it makes the code even cleaner, compared to the "then" chaining:

(async () => {
   try {
    await this.props.actions.async1(this.state.data1);
    await this.props.actions.async2(this.state.data2) 
    this.setState({ load: false );
   } catch (e) {
    this.setState({load: false, notify: "error"});
   }
})();

Of course it is a matter of taste.

EDIT : Added missing bracket



来源:https://stackoverflow.com/questions/43370176/using-async-setstate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!