Skip to main content

Redux 常见问题解答:不可变数据

¥Redux FAQ: Immutable Data

目录

¥Table of Contents

不可变性有什么好处?

¥What are the benefits of immutability?

不可变性可以为你的应用带来更高的性能,并简化编程和调试,因为从不更改的数据比在整个应用中可以随意更改的数据更容易推断。

¥Immutability can bring increased performance to your app, and leads to simpler programming and debugging, as data that never changes is easier to reason about than data that is free to be changed arbitrarily throughout your app.

特别是,Web 应用上下文中的不可变性使得复杂的变更检测技术能够简单且廉价地实现,从而确保更新 DOM 的计算成本高昂的过程仅在绝对必要时发生(这是 React 相对于其他库性能改进的基石)。

¥In particular, immutability in the context of a Web app enables sophisticated change detection techniques to be implemented simply and cheaply, ensuring the computationally expensive process of updating the DOM occurs only when it absolutely has to (a cornerstone of React’s performance improvements over other libraries).

更多信息

¥Further information

文章

¥Articles

为什么 Redux 需要不可变性?

¥Why is immutability required by Redux?

更多信息

¥Further Information

文档

¥Documentation

讨论

¥Discussions

为什么 Redux 使用浅层相等性检查需要不可变性?

¥Why does Redux’s use of shallow equality checking require immutability?

如果要正确更新任何连接的组件,Redux 使用浅层相等检查需要不可变性。要了解原因,我们需要了解 JavaScript 中浅层相等检查和深层相等检查之间的区别。

¥Redux's use of shallow equality checking requires immutability if any connected components are to be updated correctly. To see why, we need to understand the difference between shallow and deep equality checking in JavaScript.

浅层和深层平等检查有何不同?

¥How do shallow and deep equality checking differ?

浅层相等检查(或引用相等)只是检查两个不同的变量引用同一个对象;相反,深度相等检查(或值相等)必须检查两个对象属性的每个值。

¥Shallow equality checking (or reference equality) simply checks that two different variables reference the same object; in contrast, deep equality checking (or value equality) must check every value of two objects' properties.

因此,浅层相等性检查与 a === b 一样简单(且快速),而深度相等性检查涉及递归遍历两个对象的属性,在每个步骤中比较每个属性的值。

¥A shallow equality check is therefore as simple (and as fast) as a === b, whereas a deep equality check involves a recursive traversal through the properties of two objects, comparing the value of each property at each step.

为了提高性能,Redux 使用浅层相等检查。

¥It's for this improvement in performance that Redux uses shallow equality checking.

更多信息

¥Further Information

文章

¥Articles

Redux 如何使用浅层相等检查?

¥How does Redux use shallow equality checking?

Redux 在其 combineReducers 函数中使用浅层相等检查来返回根状态对象的新修改副本,或者如果未进行任何修改,则返回当前根状态对象。

¥Redux uses shallow equality checking in its combineReducers function to return either a new mutated copy of the root state object, or, if no mutations have been made, the current root state object.

更多信息

¥Further Information

文档

¥Documentation

combineReducers 如何使用浅层相等检查?

¥How does combineReducers use shallow equality checking?

Redux store 的 建议结构 是将状态对象按 key 拆分为多个 "切片" 或 "domains",并提供单独的 reducer 函数来管理每个单独的数据片。

¥The suggested structure for a Redux store is to split the state object into multiple "slices" or "domains" by key, and provide a separate reducer function to manage each individual data slice.

combineReducers 通过采用 reducers 参数使使用这种类型的结构变得更容易,该参数被定义为包含一组键/值对的哈希表,其中每个键是状态切片的名称,相应的值是将作用于它的 reducer 函数。

¥combineReducers makes working with this style of structure easier by taking a reducers argument that’s defined as a hash table comprising a set of key/value pairs, where each key is the name of a state slice, and the corresponding value is the reducer function that will act on it.

因此,例如,如果你的状态形状是 { todos, counter },则对 combineReducers 的调用将是:

¥So, for example, if your state shape is { todos, counter }, the call to combineReducers would be:

combineReducers({ todos: myTodosReducer, counter: myCounterReducer })

在哪里:

¥where:

  • todoscounter 各自引用一个单独的状态片;

    ¥the keys todos and counter each refer to a separate state slice;

  • myTodosReducermyCounterReducer 是化简器函数,每个函数都作用于由相应键标识的状态切片。

    ¥the values myTodosReducer and myCounterReducer are reducer functions, with each acting on the state slice identified by the respective key.

combineReducers 迭代每个键/值对。对于每次迭代,它:

¥combineReducers iterates through each of these key/value pairs. For each iteration, it:

  • 创建对每个键引用的当前状态片的引用;

    ¥creates a reference to the current state slice referred to by each key;

  • 调用适当的 reducer 并将切片传递给它;

    ¥calls the appropriate reducer and passes it the slice;

  • 创建对 reducer 返回的可能发生变化的状态切片的引用。

    ¥creates a reference to the possibly-mutated state slice that's returned by the reducer.

随着迭代的继续,combineReducers 将使用每个 reducer 返回的状态切片构造一个新的状态对象。这个新的状态对象可能与当前状态对象不同,也可能不同。正是在这里,combineReducers 使用浅层相等检查来确定状态是否已更改。

¥As it continues through the iterations, combineReducers will construct a new state object with the state slices returned from each reducer. This new state object may or may not be different from the current state object. It is here that combineReducers uses shallow equality checking to determine whether the state has changed.

具体来说,在迭代的每个阶段,combineReducers 对当前状态片和从 reducer 返回的状态片进行浅层相等检查。如果 reducer 返回一个新对象,浅层相等检查将失败,并且 combineReducers 会将 hasChanged 标志设置为 true。

¥Specifically, at each stage of the iteration, combineReducers performs a shallow equality check on the current state slice and the state slice returned from the reducer. If the reducer returns a new object, the shallow equality check will fail, and combineReducers will set a hasChanged flag to true.

迭代完成后,combineReducers 将检查 hasChanged 标志的状态。如果为 true,则返回新构造的状态对象。如果为 false,则返回当前状态对象。

¥After the iterations have completed, combineReducers will check the state of the hasChanged flag. If it’s true, the newly-constructed state object will be returned. If it’s false, the current state object is returned.

这点值得强调:如果 reducers 都返回传递给它们的相同的 state 对象,那么 combineReducers 将返回当前的根状态对象,而不是新更新的根状态对象。

¥This is worth emphasizing: If the reducers all return the same state object passed to them, then combineReducers will return the current root state object, not the newly updated one.

更多信息

¥Further Information

文档

¥Documentation

视频

¥Video

React-Redux 如何使用浅层相等检查?

¥How does React-Redux use shallow equality checking?

React-Redux 使用浅层相等检查来确定它所封装的组件是否需要重新渲染。

¥React-Redux uses shallow equality checking to determine whether the component it’s wrapping needs to be re-rendered.

为此,它假设封装的组件是纯的;也就是说,该组件将生成 给定相同的 props 和 state 的结果相同

¥To do this, it assumes that the wrapped component is pure; that is, that the component will produce the same results given the same props and state.

假设封装的组件是纯组件,它只需要检查根状态对象或从 mapStateToProps 返回的值是否已更改。如果没有,则封装的组件不需要重新渲染。

¥By assuming the wrapped component is pure, it need only check whether the root state object or the values returned from mapStateToProps have changed. If they haven’t, the wrapped component does not need re-rendering.

它通过保留对根状态对象的引用以及对从 mapStateToProps 函数返回的 props 对象中每个值的引用来检测更改。

¥It detects a change by keeping a reference to the root state object, and a reference to each value in the props object that's returned from the mapStateToProps function.

然后,它对根状态对象和传递给它的状态对象的引用运行浅层相等检查,并对 props 对象的值的每个引用以及再次运行 mapStateToProps 函数返回的值进行一系列单独的浅层检查。

¥It then runs a shallow equality check on its reference to the root state object and the state object passed to it, and a separate series of shallow checks on each reference to the props object’s values and those that are returned from running the mapStateToProps function again.

更多信息

¥Further Information

文档

¥Documentation

文章

¥Articles

为什么 React-Redux 会浅层检查从 mapStateToProp 返回的 props 对象中的每个值?

¥Why does React-Redux shallowly check each value within the props object returned from mapStateToProp?

React-Redux 对 props 对象中的每个值(而不是 props 对象本身)执行浅层相等检查。

¥React-Redux performs a shallow equality check on each value within the props object, not on the props object itself.

这样做是因为 props 对象实际上是 prop 名称及其值(或用于检索或生成值的选择器函数)的哈希值,例如本例中:

¥It does so because the props object is actually a hash of prop names and their values (or selector functions that are used to retrieve or generate the values), such as in this example:

function mapStateToProps(state) {
return {
todos: state.todos, // prop value
visibleTodos: getVisibleTodos(state) // selector
}
}

export default connect(mapStateToProps)(TodoApp)

因此,对重复调用 mapStateToProps 返回的 props 对象进行浅层相等性检查总是会失败,因为每次都会返回一个新对象。

¥As such, a shallow equality check of the props object returned from repeated calls to mapStateToProps would always fail, as a new object would be returned each time.

因此,React-Redux 维护对返回的 props 对象中每个值的单独引用。

¥React-Redux therefore maintains separate references to each value in the returned props object.

更多信息

¥Further Information

文章

¥Articles

React-Redux 如何使用浅层相等检查来确定组件是否需要重新渲染?

¥How does React-Redux use shallow equality checking to determine whether a component needs re-rendering?

每次调用 React-Redux 的 connect 函数时,它将对其存储的根状态对象引用以及从存储传递给它的当前根状态对象执行浅层相等检查。如果检查通过,则根状态对象尚未更新,因此不需要重新渲染组件,甚至不需要调用 mapStateToProps

¥Each time React-Redux’s connect function is called, it will perform a shallow equality check on its stored reference to the root state object, and the current root state object passed to it from the store. If the check passes, the root state object has not been updated, and so there is no need to re-render the component, or even call mapStateToProps.

但是,如果检查失败,则根状态对象已更新,因此 connect 将调用 mapStateToProps 来查看封装组件的 props 是否已更新。

¥If the check fails, however, the root state object has been updated, and so connect will call mapStateToPropsto see if the props for the wrapped component have been updated.

它通过对对象中的每个值单独执行浅层相等检查来实现此目的,并且仅在其中一项检查失败时才会触发重新渲染。

¥It does this by performing a shallow equality check on each value within the object individually, and will only trigger a re-render if one of those checks fails.

在下面的示例中,如果 state.todos 和从 getVisibleTodos() 返回的值在连续调用 connect 时没有改变,则组件将不会重新渲染。

¥In the example below, if state.todos and the value returned from getVisibleTodos() do not change on successive calls to connect, then the component will not re-render .

function mapStateToProps(state) {
return {
todos: state.todos, // prop value
visibleTodos: getVisibleTodos(state) // selector
}
}

export default connect(mapStateToProps)(TodoApp)

相反,在下一个示例(如下)中,组件将始终重新渲染,因为 todos 的值始终是一个新对象,无论其值是否更改:

¥Conversely, in this next example (below), the component will always re-render, as the value of todos is always a new object, regardless of whether or not its values change:

// AVOID - will always cause a re-render
function mapStateToProps(state) {
return {
// todos always references a newly-created object
todos: {
all: state.todos,
visibleTodos: getVisibleTodos(state)
}
}
}

export default connect(mapStateToProps)(TodoApp)

如果从 mapStateToProps 返回的新值与 React-Redux 保留引用的先前值之间的浅层相等检查失败,则会触发组件的重新渲染。

¥If the shallow equality check fails between the new values returned from mapStateToProps and the previous values that React-Redux kept a reference to, then a re-rendering of the component will be triggered.

更多信息

¥Further Information

文章

¥Articles

讨论

¥Discussions

为什么浅层相等检查不适用于可变对象?

¥Why will shallow equality checking not work with mutable objects?

如果该对象是可变的,则不能使用浅层相等检查来检测函数是否会改变传递给它的对象。

¥Shallow equality checking cannot be used to detect if a function mutates an object passed into it if that object is mutable.

这是因为引用同一个对象的两个变量将始终相等,无论对象的值是否更改,因为它们都引用同一个对象。因此,以下内容将始终返回 true:

¥This is because two variables that reference the same object will always be equal, regardless of whether the object’s values changes or not, as they're both referencing the same object. Thus, the following will always return true:

function mutateObj(obj) {
obj.key = 'newValue'
return obj
}

const param = { key: 'originalValue' }
const returnVal = mutateObj(param)

param === returnVal
//> true

paramreturnValue 的浅层检查只是检查两个变量是否引用同一个对象,它们确实这样做了。mutateObj() 可能返回 obj 的修改版本,但它仍然与传入的对象相同。事实上,它的值在 mutateObj 内发生了变化,对于浅层检查来说根本不重要。

¥The shallow check of param and returnValue simply checks whether both variables reference the same object, which they do.mutateObj() may return a mutated version of obj, but it's still the same object as that passed in. The fact that its values have been changed within mutateObj matters not at all to a shallow check.

更多信息

¥Further Information

文章

¥Articles

使用可变对象进行浅层相等检查是否会导致 Redux 出现问题?

¥Does shallow equality checking with a mutable object cause problems with Redux?

对可变对象进行浅层相等性检查不会导致 Redux 出现问题,但 它会导致依赖于存储的库出现问题,例如 React-Redux 会出现问题。

¥Shallow equality checking with a mutable object will not cause problems with Redux, but it will cause problems with libraries that depend on the store, such as React-Redux.

具体来说,如果 combineReducers 传递给 reducer 的状态片是一个可变对象,那么 reducer 可以直接修改它并返回它。

¥Specifically, if the state slice passed to a reducer by combineReducers is a mutable object, the reducer can modify it directly and return it.

如果确实如此,则 combineReducers 执行的浅层相等检查将始终通过,因为 reducer 返回的状态切片的值可能已发生变化,但对象本身并未发生变化。 - 它仍然是传递给 reducer 的同一个对象。

¥If it does, the shallow equality check that combineReducers performs will always pass, as the values of the state slice returned by the reducer may have been mutated, but the object itself has not - it’s still the same object that was passed to the reducer.

因此,即使状态已更改,combineReducers 也不会设置其 hasChanged 标志。如果其他 reducer 都没有返回新的、更新的状态切片,则 hasChanged 标志将保持设置为 false,导致 combineReducers 返回现有的根状态对象。

¥Accordingly, combineReducers will not set its hasChanged flag, even though the state has changed. If none of the other reducers return a new, updated state slice, the hasChanged flag will remain set to false, causing combineReducers to return the existing root state object.

存储仍将使用根状态的新值进行更新,但由于根状态对象本身仍然是同一对象,因此绑定到 Redux 的库(例如 React-Redux)将不会意识到状态的突变,因此不会触发封装组件的重新渲染。

¥The store will still be updated with the new values for the root state, but because the root state object itself is still the same object, libraries that bind to Redux, such as React-Redux, will not be aware of the state’s mutation, and so will not trigger a wrapped component’s re-rendering.

更多信息

¥Further Information

文档

¥Documentation

为什么 reducer 改变状态会阻止 React-Redux 重新渲染封装的组件?

¥Why does a reducer mutating the state prevent React-Redux from re-rendering a wrapped component?

如果 Redux reducer 直接修改并返回传递给它的状态对象,根状态对象的值将会改变,但对象本身不会改变。

¥If a Redux reducer directly mutates, and returns, the state object passed into it, the values of the root state object will change, but the object itself will not.

由于 React-Redux 对根状态对象执行浅层检查以确定其封装组件是否需要重新渲染,因此它将无法检测状态突变,因此不会触发重新渲染。

¥Because React-Redux performs a shallow check on the root state object to determine if its wrapped components need re-rendering or not, it will not be able to detect the state mutation, and so will not trigger a re-rendering.

更多信息

¥Further Information

文档

¥Documentation

为什么选择器修改并将持久对象返回到 mapStateToProps 会阻止 React-Redux 重新渲染封装的组件?

¥Why does a selector mutating and returning a persistent object to mapStateToProps prevent React-Redux from re-rendering a wrapped component?

如果从 mapStateToProps 返回的 props 对象的值之一是一个在对 connect 的调用中持续存在的对象(例如,可能是根状态对象),但直接突变并由选择器函数返回,React-Redux 将无法检测到突变,因此不会触发封装组件的重新渲染。

¥If one of the values of the props object returned from mapStateToProps is an object that persists across calls to connect (such as, potentially, the root state object), yet is directly mutated and returned by a selector function, React-Redux will not be able to detect the mutation, and so will not trigger a re-render of the wrapped component.

正如我们所看到的,选择器函数返回的可变对象中的值可能已经改变,但对象本身没有改变,浅层相等检查只比较对象本身,而不是它们的值。

¥As we’ve seen, the values in the mutable object returned by the selector function may have changed, but the object itself has not, and shallow equality checking only compares the objects themselves, not their values.

例如,以下 mapStateToProps 函数永远不会触发重新渲染:

¥For example, the following mapStateToProps function will never trigger a re-render:

// State object held in the Redux store
const state = {
user: {
accessCount: 0,
name: 'keith'
}
}

// Selector function
const getUser = state => {
++state.user.accessCount // mutate the state object
return state
}

// mapStateToProps
const mapStateToProps = state => ({
// The object returned from getUser() is always
// the same object, so this wrapped
// component will never re-render, even though it's been
// mutated
userRecord: getUser(state)
})

const a = mapStateToProps(state)
const b = mapStateToProps(state)

a.userRecord === b.userRecord
//> true

请注意,相反,如果使用不可变对象,则 组件可能会在不应该重新渲染的时候重新渲染

¥Note that, conversely, if an immutable object is used, the component may re-render when it should not.

更多信息

¥Further Information

文章

¥Articles

讨论

¥Discussions

不可变性如何启用浅层检查来检测对象突变?

¥How does immutability enable a shallow check to detect object mutations?

如果对象是不可变的,则需要在函数内对其进行的任何更改都必须针对该对象的副本进行。

¥If an object is immutable, any changes that need to be made to it within a function must be made to a copy of the object.

这个修改的副本是一个与传入函数的对象不同的对象,因此当它返回时,浅层检查会将其识别为与传入的对象不同的对象,因此会失败。

¥This mutated copy is a separate object from that passed into the function, and so when it is returned, a shallow check will identify it as being a different object from that passed in, and so will fail.

更多信息

¥Further Information

文章

¥Articles

reducer 中的不可变性如何导致组件不必要地渲染?

¥How can immutability in your reducers cause components to render unnecessarily?

你不能改变一个不可变的对象;相反,你必须改变它的副本,而保持原始的完整。

¥You cannot mutate an immutable object; instead, you must mutate a copy of it, leaving the original intact.

当你改变副本时,这是完全可以的,但在 reducer 的上下文中,如果你返回一个尚未改变的副本,Redux 的 combineReducers 函数仍然会认为状态需要更新,因为你返回的对象与传入的状态切片对象完全不同。

¥That’s perfectly OK when you mutate the copy, but in the context of a reducer, if you return a copy that hasn’t been mutated, Redux’s combineReducers function will still think that the state needs to be updated, as you're returning an entirely different object from the state slice object that was passed in.

然后,combineReducers 会将这个新的根状态对象返回到存储区。新对象将具有与当前根状态对象相同的值,但由于它是不同的对象,因此将导致存储更新,这最终将导致所有连接的组件不必要地重新渲染。

¥combineReducers will then return this new root state object to the store. The new object will have the same values as the current root state object, but because it's a different object, it will cause the store to be updated, which will ultimately cause all connected components to be re-rendered unnecessarily.

为了防止这种情况发生,如果 reducer 不改变状态,则必须始终返回传递到 reducer 的状态切片对象。

¥To prevent this from happening, you must always return the state slice object that’s passed into a reducer if the reducer does not mutate the state.

更多信息

¥Further Information

文章

¥Articles

mapStateToProps 中的不可变性如何导致组件不必要地渲染?

¥How can immutability in mapStateToProps cause components to render unnecessarily?

某些不可变操作(例如数组过滤器)将始终返回一个新对象,即使值本身没有更改。

¥Certain immutable operations, such as an Array filter, will always return a new object, even if the values themselves have not changed.

如果这样的操作在 mapStateToProps 中用作选择器函数,React-Redux 对返回的 props 对象中的每个值执行的浅层相等检查将始终失败,因为选择器每次都会返回一个新对象。

¥If such an operation is used as a selector function in mapStateToProps, the shallow equality check that React-Redux performs on each value in the props object that’s returned will always fail, as the selector is returning a new object each time.

因此,即使该新对象的值没有改变,封装的组件也将始终被重新渲染,

¥As such, even though the values of that new object have not changed, the wrapped component will always be re-rendered,

例如,以下内容始终会触发重新渲染:

¥For example, the following will always trigger a re-render:

// A JavaScript array's 'filter' method treats the array as immutable,
// and returns a filtered copy of the array.
const getVisibleTodos = todos => todos.filter(t => !t.completed)

const state = {
todos: [
{
text: 'do todo 1',
completed: false
},
{
text: 'do todo 2',
completed: true
}
]
}

const mapStateToProps = state => ({
// getVisibleTodos() always returns a new array, and so the
// 'visibleToDos' prop will always reference a different array,
// causing the wrapped component to re-render, even if the array's
// values haven't changed
visibleToDos: getVisibleTodos(state.todos)
})

const a = mapStateToProps(state)
// Call mapStateToProps(state) again with exactly the same arguments
const b = mapStateToProps(state)

a.visibleToDos
//> { "completed": false, "text": "do todo 1" }

b.visibleToDos
//> { "completed": false, "text": "do todo 1" }

a.visibleToDos === b.visibleToDos
//> false

请注意,相反,如果 props 对象中的值引用可变对象,则 你的组件可能不会在应该渲染的时候渲染

¥Note that, conversely, if the values in your props object refer to mutable objects, your component may not render when it should.

更多信息

¥Further Information

文章

¥Articles

有哪些方法可以处理数据不可变性?我必须使用 Immer 吗?

¥What approaches are there for handling data immutability? Do I have to use Immer?

你不需要将 Immer 与 Redux 一起使用。如果编写正确,纯 JavaScript 完全能够提供不可变性,而无需使用以不可变为中心的库。

¥You do not need to use Immer with Redux. Plain JavaScript, if written correctly, is perfectly capable of providing immutability without having to use an immutable-focused library.

然而,用 JavaScript 保证不可变性很困难,而且很容易意外地改变对象,从而导致应用中出现极难定位的错误。因此,使用 Immer 这样的不可变更新实用程序库可以显着提高应用的可靠性,并使应用的开发变得更加容易。

¥However, guaranteeing immutability with JavaScript is difficult, and it can be easy to mutate an object accidentally, causing bugs in your app that are extremely difficult to locate. For this reason, using an immutable update utility library such as Immer can significantly improve the reliability of your app, and make your app’s development much easier.

更多信息

¥Further Information

讨论

¥Discussions

使用纯 JavaScript 进行不可变操作有哪些问题?

¥What are the issues with using plain JavaScript for immutable operations?

JavaScript 从来就不是为了提供有保证的不可变操作而设计的。因此,如果你选择将其用于 Redux 应用中的不可变操作,则需要注意几个问题。

¥JavaScript was never designed to provide guaranteed immutable operations. Accordingly, there are several issues you need to be aware of if you choose to use it for your immutable operations in your Redux app.

意外的对象突变

¥Accidental Object Mutation

使用 JavaScript,你可能会很容易地意外地改变一个对象(例如 Redux 状态树),而没有意识到。例如,更新深层嵌套属性、创建对对象的新引用而不是新对象,或者执行浅复制而不是深复制,都可能导致无意的对象突变,甚至可能使最有经验的 JavaScript 编码人员陷入困境。

¥With JavaScript, you can accidentally mutate an object (such as the Redux state tree) quite easily without realizing it. For example, updating deeply nested properties, creating a new reference to an object instead of a new object, or performing a shallow copy rather than a deep copy, can all lead to inadvertent object mutations, and can trip up even the most experienced JavaScript coder.

为了避免这些问题,请确保遵循建议的 不可变的更新模式

¥To avoid these issues, ensure you follow the recommended immutable update patterns.

详细代码

¥Verbose Code

更新复杂的嵌套状态树可能会导致编写冗长且难以调试的冗长代码。

¥Updating complex nested state trees can lead to verbose code that is tedious to write and difficult to debug.

表现不佳

¥Poor Performance

以不可变的方式操作 JavaScript 对象和数组可能会很慢,尤其是当状态树变大时。

¥Operating on JavaScript objects and arrays in an immutable way can be slow, particularly as your state tree grows larger.

请记住,要更改不可变对象,你必须更改它的副本,并且复制大型对象可能会很慢,因为必须复制每个属性。

¥Remember, to change an immutable object, you must mutate a copy of it, and copying large objects can be slow as every property must be copied.

相比之下,诸如 Immer 之类的不可变库可以采用结构共享,这可以有效地返回一个新对象,该新对象可以重用从中复制的大部分现有对象。

¥In contrast, immutable libraries such as Immer can employ structural sharing, which effectively returns a new object that reuses much of the existing object being copied from.

更多信息

¥Further Information

文档

¥Documentation

文章

¥Articles