Redux 只是一个数据存储。因此,就其纯粹 的意义而言,redux 并不真正需要 不变性或深度克隆来作为一个概念工作。
但是,redux 需要不可变性才能很好地与构建在它之上的 UI 框架(例如 React)一起工作。
出于这个简单的原因:我的状态的哪些部分在上次查看框架时发生了变化?
鉴于这个目标,您能看出深度克隆实际上是如何无济于事的吗?如果您查看一个已被深度克隆的对象,那么该对象的每个子部分现在在身份方面都不同 (===)。
作为一个具体的例子,如果你运行以下代码:
const bookstore = { name: "Jane's books", numBooks: 42 };
const reduxData = { bookstore, employees: ['Ada', 'Bear'] };
现在假设您只想更改书店的图书数量。
如果你做了一个深拷贝,像这样:
const reduxClone = JSON.parse(JSON.stringify(reduxData));
reduxClone.bookstore.numBooks = 25;
然后你会看到书店和员工现在都不同了:
console.log(reduxData.bookstore === reduxClone.bookstore); // returns false
console.log(reduxData.employees === reduxClone.employees); // returns false, but we haven't changed the employees
这是一个问题,因为看起来一切都发生了变化。现在 React 必须重新渲染所有内容以查看是否有任何变化。
正确的解决方案是使用简单的不变性规则。如果更改对象的值,则必须创建该对象的新副本。所以,既然我们想要一个新的 numBooks,我们需要创建一个新的书店。既然我们有一个新书店,我们需要做一个新的 redux 商店。
const newBookstore = Object.assign({}, bookstore, {numBooks: 25});
const shallowReduxClone = Object.assign({}, reduxData, {bookstore: newBookstore});
现在,您会看到书店发生了变化(耶!),但员工却没有(双倍耶!)
console.log(reduxData.bookstore === shallowReduxClone.bookstore); // returns false
console.log(reduxData.employees === shallowReduxClone.employees); // returns true
我希望这个例子有帮助。不变性允许您在进行更改时更改最少的对象量。如果您保证永远不会更改对象,那么您可以在您构建的其他树中重用该对象。在这个例子中,我们可以使用employees 对象两次,没有危险,因为我们承诺永远不会改变employees 对象。