0

I have a situation when it would be really convenient to have a promise object as a part of the state. In short - there is a state which contains all the info which user gave in the question-answer mode and after some answer it would be nice to send a call, result of which will be needed after several more questions:

Q1 -> Q2 -> Q3 - -> Q4 - - -> Q5 -> Q6 -> Q7 
                 \ - - Call to API - - /

Before Q7 I need to check result of call after Q3. It would be really easy to do with promise as a part of the state and then just subscribe to result. But I have inner feeling that it should not happen. Is it ok to do it this way?

I don't think that my code will help to understand, so feel free to just ask questions if it's not clear.

Vladyslav Zavalykhatko
  • 15,202
  • 8
  • 65
  • 100

2 Answers2

1

You can use redux-promise middleware, Your actions will return you promise if that action is completed, in-flight or failed. So you can easily manage questions and make call exactly at the right time you needed based on the promise. I have a sample example in my github account which shall explain how to use it. Let know if you find it useful.

Below is suedo code

Action controller

export const action_CALL = () => {
  return {
    type: SOME_CALL,
    payload: new Promise((resolve, reject) => {
                let wait = setTimeout(() => {
                resolve('DUMMY ... Few questions answered in x mins');
              }, 2000)
    }),
  };
};

Reducer

export const countReducer = typeToReducer({
  [SOME_CALL]: {
    PENDING: (state, action) => ({
      ...state,
      answered: false,
    }),
    REJECTED: (state) => ({
      ...state,
      answered: false,
    }),
    FULFILLED: (state, action) => ({
      answered: true,
      callResponse: action.payload,
    })
  }
}, initState);

This approach will give you fine-grained control.

mbarish-me
  • 897
  • 1
  • 14
  • 25
1

You should not do that because serializing your state would not be possible anymore. How much of a problem that is, not sure, it might only break the devtools or some persistence/hydration library you are using or will use. But to stay true to redux and its simplicity, reduce your scenario to a single truth:

  • Is the current question past Q3 but still before Q7? I imagine a selector could determine that because the current question is surely part of the state already.
  • Has a request been made to fetch the data?

Based on that you send the request:

if (currentQuestion > 3 && currentQuestion < 7 && !isDataRequested) {
    dispatch(callToApi()); // this sets isDataRequested to true.
}

This will work with persisting and hydrating the state.

timotgl
  • 2,865
  • 1
  • 9
  • 19
  • so basically, you advise having kind-of `promiseState` without promise itself. as `isDataRequested` is not enough for me. I need also to know if it failed and if it completed – Vladyslav Zavalykhatko Apr 12 '18 at 16:43
  • just to make my situation a bit more clear, I have this `answer-results` in different sub-reducers. it looks like `store.dispatch(setCustomer(customer))` -> `func customerReducer(state, action) {//return new state with customer}` and more things like that. I hope it's clear :) – Vladyslav Zavalykhatko Apr 12 '18 at 16:47
  • @VladyslavZavalykhatko You can add the result of the api call to the condition then. `!isDataRequested && !success` (however success is determined). If you want to retry on failure it gets a bit more complicated, but same with an actual promise. – timotgl Apr 13 '18 at 07:18