一個全新的狀態對象將在每一個動作
是的,但是由combineReducers
分配不會被重建該國的片創建。這有點類似於這樣:
const person = { name: 'Rob' };
const prevState = { person };
const nextState = { person };
我創建了一個新的狀態對象(nextState
),但其person
關鍵仍設置爲完全相同的對象是prevState
的person
關鍵。內存中只有一個字符串'Rob'
的實例。
問題是,當我的變異對象person
,我改變了它的多種狀態:
const person = { name: 'Rob' };
const prevState = { person };
person.name = 'Dan'; // mutation
const nextState = { person };
console.log(prevState.person.name); // 'Dan'
反觀Redux的,一旦所有減速都被稱爲是第一次,他們將初始化他們的應用程序的狀態,以及應用程序的整個整體狀態的片將基本上等於這樣的:
{
firstReducer: Immutable.Map({greeting : 'Hey!'}),
secondReducer: Immutable.Map({foo : 'bar'}),
}
注意,這是一個正常的對象。它具有保存不可變對象的屬性。
當一個動作被調度並且通過每個reducer時,就會得到它,reducer只是簡單地返回現有的Immutable對象,它不會創建一個新的。然後,將新狀態設置爲一個對象,該對象的屬性firstReducer
只是簡單地指向與之前狀態指向的相同的不可變對象。現在
,如果我們沒有爲firstReducer
用什麼永恆:
const firstReducer = (state = {greeting : 'Hey!'}) => {
return state
}
同樣的想法,那就是用作默認爲在減速機首次調用只是從以前的狀態傳遞狀態對象到下一個狀態。內存中只有一個對象具有密鑰greeting
和值Hey!
。有許多狀態對象,但它們只有一個指向相同對象的密鑰firstReducer
。
這就是爲什麼我們需要確保我們不會意外地改變它,而是在我們改變它的任何事情時將其替換掉。你可以通過小心來完成這項工作,而不用固定,但使用Immutable使它更加簡單。沒有一成不變的,它可能搞砸了,並做到這一點:
const firstReducer = (state = {greeting : 'Hey!'}, action) => {
switch (action.type) {
case 'CAPITALIZE_GREETING': {
const capitalized = state.greeting.toUpperCase();
state.greeting = capitalized; // BAD!!!
return state;
}
default: {
return state;
}
}
}
的正確方法是創建一個新的狀態切片:
const firstReducer = (state = {greeting : 'Hey!'}, action) => {
switch (action.type) {
case 'CAPITALIZE_GREETING': {
const capitalized = state.greeting.toUpperCase();
const nextState = Object.assign({}, state, {
greeting: capitalized,
};
return nextState;
}
default: {
return state;
}
}
}
另一個好處永恆帶給我們的是,如果我們的減速機的片除了greeting
之外,Immutable可能會進行一些優化,因此如果我們所做的只是更改單個值,但它仍然不需要重新創建每一條數據確保不變的同時。這非常有用,因爲它可以幫助減少每次分派操作時內存中內存的數量。
謝謝你的回答。我主要是指內存使用和新對象的創建。羅布在他的回答中釘了它。 – swelet
啊,我明白了。常見問題也涉及這個主題:http://redux.js.org/docs/FAQ.html#performance-clone-state –