I am using react, with redux for state management. In my UI I have a button which when clicked it calls a function and that function internally calls 2 redux actions that perform the specific task. The problem is my function when I make a call after a click of the button it immediately calls both the functions.
This is my on button click function
const handleDecrement = (productId) => {
props.minusQuantity(productId, props.guestIdData); // call make to redux action to perform API action
props.quantityData.forEach((item) => {
if (item.productQuantity < 1) { // value of state. Which is instantly changed
props.removeWholeItem(productId); // Another API call to redux action
}
});
};
I want to call this function first
props.minusQuantity(productId, props.guestIdData);
and thnen later the following code
props.quantityData.forEach((item) => {
if (item.productQuantity < 1) { // value of state. Which is instantly changed
props.removeWholeItem(productId); // Another API call to redux action
}
});
Use redux-thunk and bind your button onClick function as async.
handleClick = async () => {
await props.actions.someReduxThunkFn();
await props.actions.otherReduxThunkFn();
}
You can use.then and.catch and makes function calls one after another.
props.minusQuantity(productId, props.guestIdData).then(response=>{ props.removeWholeItem(productId) })
Assuming that minusQuantity is a thunk action that returns a promise you can await it:
const minusQuantity = (productId, guestIdData) => (
dispatch,
getState
) => {
return Promise.resolve('async value');
};
Now both of the other answers would work:
const handleDecrement = async (productId) => {
await props.minusQuantity(productId, props.guestIdData);
or
const handleDecrement = (productId) => {
props.minusQuantity(productId, props.guestIdData).then(
()=>{
//do other stuff here
}
)
Working example:
const { Provider, connect } = ReactRedux; const { createStore, applyMiddleware, compose } = Redux; const initialState = {}; //action types const BEFORE_ASYNC = 'BEFORE_ASYNC'; const AFTER_ASYNC = 'AFTER_ASYNC'; //action creators const minusQuantity = () => (dispatch) => { dispatch({ type: BEFORE_ASYNC }); //note it is returning a promise return new Promise((resolve) => setTimeout( () => resolve(dispatch({ type: AFTER_ASYNC })), 2000 ) ); }; const reducer = (state, { type }) => { console.log('reducer called with action:', type); return state; }; //creating store with redux dev tools const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; const store = createStore( reducer, initialState, composeEnhancers( applyMiddleware((store) => (next) => (action) => typeof action === 'function' //DIY thunk middleware? action(store.dispatch): next(action) ) ) ); const App = (props) => { const handleDecrement = (productId) => { console.log('in handeDecrement starting async action'); props.minusQuantity(productId).then(() => console.log('in handleDecrement after async action') ); }; return ( <button onClick={handleDecrement}> start async action </button> ); }; const AppContainer = connect(undefined, { minusQuantity, })(App); ReactDOM.render( <Provider store={store}> <AppContainer /> </Provider>, document.getElementById('root') );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script> <div id="root"></div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.