Vladyslav Zavalykhatko
Vladyslav Zavalykhatko

Reputation: 17384

Promise as a part of state in redux

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.

Upvotes: 0

Views: 258

Answers (2)

timotgl
timotgl

Reputation: 2925

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.

Upvotes: 1

mbarish-me
mbarish-me

Reputation: 957

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.

Upvotes: 1

Related Questions