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.
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 })
})
})
}
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
Here's what you can do...
- Change your action to take in a
onFetchComplete
callback, along with theinput
. 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.
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
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));
}
来源:https://stackoverflow.com/questions/43370176/using-async-setstate