Reputation: 4066
Can I update the state based on other state variables (as shown below in setCurrentQuestion()
), or will it cause unexpected issues?
I can think of two workarounds:
getCurrentQuestionIndex()
selector passed into a getQuestionByIndex()
selector which returns an IQuestion
object that I pass into the setCurrentQuestion()
reducerconst slice = createSlice({
name: 'blabla',
initialState: { questions: undefined, currentQuestion: undefined, noOfQuestions: 0, currentQuestionIndex: 0 } as QuizState,
reducers: {
setQuestions: (state, action: PayloadAction<IQuestion[]>) => {
state.questions = action.payload;
},
setCurrentQuestion: (state, action: PayloadAction<number>) => {
if (!state.questions) return
state.currentQuestion = state.questions[state.currentQuestionIndex]
}
},
Upvotes: 0
Views: 1261
Reputation: 2925
state.currentQuestion
should simply not exist in your state. You got state.questions
as the source of truth, and state.currentQuestionIndex
to remember which question is the current question. Anything further is not atomic and minimal anymore. It certainly works to have a state.currentQuestion
which duplicates one of the items in state.questions
, but then you end up with problems like this one. I'd recommend to add a selector getCurrentQuestion()
that does the lookup and that can deal with state.questions
being falsy. It also should never not be an array btw, it's easier to deal with state if the types don't change. I'd initialise it as an empty array, and then the selector could be:
const getCurrentQuestion = (state) => state.questions[state.currentQuestionIndex];
To solve what you had in mind, looking at a different part of the state before mutating it in the reducer, you could also use a thunk - they have getState()
in the scope and can run conditional logic. So you could simply not dispatch setCurrentQuestion
if state.questions
is falsy. But a better solution imo is what I described above with the selector.
Upvotes: 1