1

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 
        }
    });
3
  • Use redux-thunk for async actions Commented Aug 7, 2020 at 7:06
  • YOu need to use redux-thunk for async actions Commented Aug 7, 2020 at 7:07
  • I am already using it. It is used to async the actions. But here I am calling redux action within the function Commented Aug 7, 2020 at 7:07

3 Answers 3

1

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>

Sign up to request clarification or add additional context in comments.

Comments

1

Use redux-thunk and bind your button onClick function as async.

handleClick = async () => {
  await props.actions.someReduxThunkFn();
  await props.actions.otherReduxThunkFn();
}

Comments

1

You can use .then and .catch and makes function calls one after another.

props.minusQuantity(productId, props.guestIdData).then(response=>{ props.removeWholeItem(productId) })

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.