什么是不变的状态?
这是一个不会随时间变化的状态。
因此,当我们创建一个不变的对象时,我们不会更改其属性,如果需要更改其属性,我们会创建其新副本,并根据需要修改属性。
在JavaScript中,我们可以同时使用可变态和不可变的状态,我们决定哪种对我们更好,我们可以使用 object.freeze.freeze()使我们的对象变得不可变。
让我们有一个例子,我们有一个称为状态的对象...
const state = {
id: 1,
name: 'John',
accounts: {
facebook: {
id: 'facebook',
url: '/'
},
twitter: {
id: 'twitter',
url: '/'
}
}
};
我们需要修改其Twitter帐户URL并将其分配给新状态而不会影响当前状态,因此我们会做类似的事情
const newState = {
...state,
accounts: { ...state.accounts, twitter: {
...state.accounts.twitter, url: '/newUrl' } }
};
此代码有两个主要问题
- 与其目的相比,我只想更新一个属性。
- 可读性不是很好,为什么我只在更新一个属性时看到许多属性和嵌套级别?!
如果我们使用Immerjs,那就像这个
const newState = produce(state, (draftState) => {
draftState.accounts.twitter.url = '/newUrl';
});
在这里,我们可以看到
- 较短的代码
- 更可读性,我只看到我正在更改的属性!
因此,Immerjs生产函数创建对象或数组的新草稿副本,并让您根据需要进行修改,然后通过应用更改返回新状态。
在反应中
所有状态都是不可变的,当我们设置一个状态时,我们创建一个新变量并将其分配给状态,我们不会更改当前一个
让我们有一个示例
const [quiz, setQuiz] = useState({
title: "Quiz 1",
questions: [
{
id: "1",
type: "mcq",
title: "Question 1?",
answers: [
{
id: "a_1",
text: "Answer 1",
isTrue: true
},
{
id: "a_2",
text: "Answer 2",
isTrue: false
}
]
}
]
});
我们已经拥有一个对象,如果我们想向测验推出新答案怎么办?我们会做这样的事情
const changeAnswer = (questionId, newAnswer) => {
setQuiz({
...quiz,
questions: quiz.questions.map((question) =>
question.id === questionId
? { ...question, answers: [...question.answers,
newAnswer] }
: question
)
});
};
复杂,对吗?这是使用Immerjs
完成的方式
const changeAnswer = (questionId, newAnswer) => {
setQuiz(produce(prev, (draft) => {
const question = draft.questions.find((el) => el.id === questionId);
question.answers.push(newAnswer);
}
);
};
因此,这不仅仅是减少代码数量,而且我们只关注我们需要更改“答案”的内容,而不必关心其他测验属性。
还有一个灯软件包使用 - 以immer 包含一个自定义挂钩使用器,它用于使用usestate以自动调用state state state
const [quiz, setQuiz] = useImmer({
.....
});
它将使我们的代码更简单
const changeAnswer = (questionId, newAnswer) => {
setQuiz((draft) => {
const question = draft.questions.find((el) => el.id === questionId);
question.answers.push(newAnswer);
});
};
这个很棒的软件包immerjs使redux工具包比旧的redux模式要简单得多,它是在此处自动实现的,因此您无需使用许多扩展操作员来更改还原器中的一个值。
非常感谢!