我不能完全包住redux的样板。我查看了immutable modifying of state的常见模式,但问题是,所有这些模式都只是推向了最后,而不是针对特定的索引。
在进入实际代码之前,这是为了更好地想象(伪代码) 的状态状态结构:
state = {
quizMenu: {...},
quizEditor: Array<Question>,
> type Question = {
id: number,
question: string,
questionOptions: Array<QuestionOption>,
}
> type QuestionOption = {
id: number,
optionText: string,
isValid: boolean,
}
}
希望这是有道理的。我创建了一个添加问题的操作,效果很好。现在,我试图创建一个操作来为现有问题添加选项,但是我无法将想法摆在嵌套对象数组中。
以下是我定义的相关行为的定义:
const AQO = 'ADD_QUESTION_OPTION';
/*
* @param questionId - ID of the question we're accesssing in quizEditor array
* @param id - id of the option we're adding (handled in component)
*/
const actionAddQuestionOption = createAction(
AQO,
(questionId: number, id: number) => ({
payload: {
id,
optionText: 'New option',
isValid: false,
questionId,
},
})
);
现在我的减速器是以下方式:
const reducer = createReducer({//...}, {
[actionAddQuestionOption.type]: (state, action) => ({
...state,
quizEditor: [...state.quizEditor][action.payload.questionId].questionOptions.push({
id: action.payload.id,
optionText: action.payload.optionText,
isValid: action.payload.isValid,
})
})
}
这最终以这种怪物类型错误结束:https://pastebin.com/raw/pBbnxcQp
但是我很确定我在错误地访问对象数组中的数组。
quizEditor: [...state.quizEditor][action.payload.questionId].questionOptions
有人知道访问它的正确方法是什么?非常感谢!
答案 0 :(得分:1)
push
的{{1}}方法返回数组的新长度,而不是数组本身。您可以做的只是将新对象Array
移到数组中,该对象又将返回带有新问题选项的新数组。
concat
此外,我们必须使用新数组在状态中仅修改该属性:
[...state.quizEditor][action.payload.questionId].questionOptions.concat({
id: action.payload.id,
optionText: action.payload.optionText,
isValid: action.payload.isValid,
})
感谢沉浸在redux工具箱中,我们可以使其更具可读性:
const reducer = createReducer({
//...}, {
[actionAddQuestionOption.type]: (state, action) => {
const quizEditor = [...state.quizEditor];
quizEditor[action.payload.questionId].questionOptions = quizEditor[
action.payload.questionId
].questionOptions.concat({
id: action.payload.id,
optionText: action.payload.optionText,
isValid: action.payload.isValid
});
return {
...state,
quizEditor
};
}
});
答案 1 :(得分:1)
由于您使用的是内置redux-toolkit的immer,因此您可以直接更改状态并将其内部转换为不可变的更新
const reducer = createReducer({
[actionAddQuestionOption.type]: (state, { payload: { questionId, ...option }}) => {
const question = state.questionquizEditor(question => question.id === questionId)
question.questionOptions.push(option)
}
})
使其成为不可更改的更新的方式如下
const reducer = createReducer({
[actionAddQuestionOption.type]: (state, { payload: { questionId, ...option } }) => ({
...state,
quizEditor: state.quizEditor.map(question =>
(question.id === questionId
? {
...question,
questionOptions: [...question.questionOptions, option],
}
: question)),
}),
})