为什么不能直接修改nestState呢?
Why can't modify the nestState directly?
在 redux docs 我看到了这个:
Common Mistake #1: New variables that point to the same objects
Defining a new variable does not create a new actual object - it only creates another reference to the same object. An example of this error would be:
function updateNestedState(state, action) {
let nestedState = state.nestedState;
// ERROR: this directly modifies the existing object reference - don't do this!
nestedState.nestedField = action.data;
return {
...state,
nestedState
};
}
This function does correctly return a shallow copy of the top-level state object, but because the nestedState
variable was still pointing at the existing object, the state was directly mutated.
但是我们知道combineReducers
只是通过顶层reference.Seeredux判断状态变化comBindReducer.js src:
let hasChanged = false
const nextState = {}
for (let i = 0; i < finalReducerKeys.length; i++) {
const key = finalReducerKeys[i]
const reducer = finalReducers[key]
const previousStateForKey = state[key]
const nextStateForKey = reducer(previousStateForKey, action)
if (typeof nextStateForKey === 'undefined') {
const errorMessage = getUndefinedStateErrorMessage(key, action)
throw new Error(errorMessage)
}
nextState[key] = nextStateForKey
hasChanged = hasChanged || nextStateForKey !== previousStateForKey
}
return hasChanged ? nextState : state
它只是访问每个reducer并判断状态引用是否发生变化。
所以回到问题,返回的对象引用已更改,因此 hasChanged
变量为真,redux 有效 fine.So 我不知道状态的副作用是什么直接?
如果知道请告诉我,谢谢
我认为该示例与 cobmineReducers
没有直接关系。我相信它试图提出与不变性相关的警告:每当复杂对象内的值发生变化时,整个层次结构都应该指出这一点。因此,如果 state.nestedState.nestedField
发生变化,则意味着 state.nestedState
发生了变化,state
也发生了变化。查看 state
或 nestedState
就足以意识到 nestedField
已更改。
刚接触这个概念的开发者,可能经常会认为把state.nestedState
赋值给一个新的变量,然后再改就好了,其实不然,因为a === state.nestedState
还是true
.
combineReducers
只关心其中一个切片是否发生了变化。如果遵循上述规则,它将 "work fine"。但是如果我们直接看 state.nestedState
会发生什么?引用仍然相同,所以它不再起作用了。
对于 React,connect
的工作方式相同。它浅比较props,依赖相同的规则:不需要深比较,因为parent应该指出child是否改变了。
回到你的问题:直接改变状态有什么副作用?
让我们用你的例子:
// reducer.js
function reducer(state, action) {
let nestedState = state.nestedState;
nestedState.nestedField = action.data;
return {
...state,
nestedState
};
}
这会很好用:
connect(state => ({ state }))(MyComponent)
这不会:
connect(state => ({ nestedState: state.nestedState }))(MyComponent)
我希望它能回答您的问题,或者至少能说明一些问题。
在 redux docs 我看到了这个:
Common Mistake #1: New variables that point to the same objects
Defining a new variable does not create a new actual object - it only creates another reference to the same object. An example of this error would be:
function updateNestedState(state, action) {
let nestedState = state.nestedState;
// ERROR: this directly modifies the existing object reference - don't do this!
nestedState.nestedField = action.data;
return {
...state,
nestedState
};
}
This function does correctly return a shallow copy of the top-level state object, but because the
nestedState
variable was still pointing at the existing object, the state was directly mutated.
但是我们知道combineReducers
只是通过顶层reference.Seeredux判断状态变化comBindReducer.js src:
let hasChanged = false
const nextState = {}
for (let i = 0; i < finalReducerKeys.length; i++) {
const key = finalReducerKeys[i]
const reducer = finalReducers[key]
const previousStateForKey = state[key]
const nextStateForKey = reducer(previousStateForKey, action)
if (typeof nextStateForKey === 'undefined') {
const errorMessage = getUndefinedStateErrorMessage(key, action)
throw new Error(errorMessage)
}
nextState[key] = nextStateForKey
hasChanged = hasChanged || nextStateForKey !== previousStateForKey
}
return hasChanged ? nextState : state
它只是访问每个reducer并判断状态引用是否发生变化。
所以回到问题,返回的对象引用已更改,因此 hasChanged
变量为真,redux 有效 fine.So 我不知道状态的副作用是什么直接?
如果知道请告诉我,谢谢
我认为该示例与 cobmineReducers
没有直接关系。我相信它试图提出与不变性相关的警告:每当复杂对象内的值发生变化时,整个层次结构都应该指出这一点。因此,如果 state.nestedState.nestedField
发生变化,则意味着 state.nestedState
发生了变化,state
也发生了变化。查看 state
或 nestedState
就足以意识到 nestedField
已更改。
刚接触这个概念的开发者,可能经常会认为把state.nestedState
赋值给一个新的变量,然后再改就好了,其实不然,因为a === state.nestedState
还是true
.
combineReducers
只关心其中一个切片是否发生了变化。如果遵循上述规则,它将 "work fine"。但是如果我们直接看 state.nestedState
会发生什么?引用仍然相同,所以它不再起作用了。
对于 React,connect
的工作方式相同。它浅比较props,依赖相同的规则:不需要深比较,因为parent应该指出child是否改变了。
回到你的问题:直接改变状态有什么副作用?
让我们用你的例子:
// reducer.js
function reducer(state, action) {
let nestedState = state.nestedState;
nestedState.nestedField = action.data;
return {
...state,
nestedState
};
}
这会很好用:
connect(state => ({ state }))(MyComponent)
这不会:
connect(state => ({ nestedState: state.nestedState }))(MyComponent)
我希望它能回答您的问题,或者至少能说明一些问题。