我有一個簡單的減速器/背景關系系統來存盤狀態。一切正常,除了我無法單獨更新欄位而不影響其他人的狀態。
問題是,當我更改其中一個AppData欄位時,其他欄位變為空白。我不知道我做錯了什么,我希望能夠更新單個值,同時保留其他欄位的值。
例如:如果我只更新appData.headerTitle值,則appData.testValueandappData.userHasLoggedOut值將被洗掉。如果我同時更新 3 個值,則不會洗掉任何內容。我希望能夠只更新一個欄位而不洗掉其余欄位。
export function AppReducer(state: AppState, action: Actions): AppState {
switch (action.type) {
case 'setAppData':
return {
...state,
appData: action.payload
};
case 'changeAppData':
return {
...state,
appData: {
...state.appData,
headerTitle: action.payload,
testValue: action.payload,
userHasLoggedOut: action.payload
}
};
}
}
具有完整作業代碼的沙箱:https ://codesandbox.io/s/frosty-cache-c6yqgx?file=/src/middlewares/reducer/AppReducer.tsx
謝謝!
我不確定在這里嘗試什么...
uj5u.com熱心網友回復:
每次您進行更改時,您都會發送一個有效負載,它是一個具有 ONE 屬性的物件,例如在App.tsx第 22 行,它是一個具有一個屬性的物件headerTitle。
所以第 9 行中的這個物件AppReducer.tsx覆寫了整個當前狀態,所以如果有任何其他屬性,它們將被覆寫并消失。
要解決此問題,我建議您傳播此有效負載以保存包含資料的先前欄位:
case "setAppData":
return {
...state,
appData: {
...state.appData,
...action.payload
}
};
提示:我其實不知道為什么在這種狀態下會有一個 appData 欄位。如果屬性直接位于該州,也許會更容易和更清潔。我的意思是,而不是這種結構
export type AppState = {
appData: {
headerTitle?: string;
testValue?: string;
userHasLoggedOut?: boolean;
};
};
使用類似的東西:
export type AppState = {
headerTitle?: string;
testValue?: string;
userHasLoggedOut?: boolean;
};
uj5u.com熱心網友回復:
你的案子有幾個問題changeAppData。還感覺您的代碼中缺少某些部分,例如changeAppDatafn 沒有在您的 useContext 掛鉤中回傳。但是據我所見,appData當您遇到這種情況時,您的所有三個值都將是相同的,changeAppData因為它們都設定為action.payload.
你可以,(我會)在這里打破你的changeAppData行動。我正在查看您的代碼框,實際上您并沒有一次更新多個值。您正在單獨更新狀態片段,因此您還可以有更多描述性操作。最重要的是,您實際上并不需要appData嵌套在狀態中的這個額外的物件層。所以也許像下面這樣
switch (action.type) {
case 'SET_HEADER_TITLE':
return {
...state,
headerTitle: action.payload,
};
case 'SET_USER_LOGGED_OUT':
return {
...state,
userHasLoggedOut: action.payload
};
default: // Don't forget your default case
break;
}
如果您堅持將它們嵌套在另一個物件下,在這種情況下是appData. 您需要從減速器中獲取狀態物件,然后將該物件與更新鍵/屬性一起傳遞。
switch (action.type) {
case 'setAppData':
return {
...state,
appData: action.payload
};
case 'UPDATE_APP_DATA':
return {
...state,
appData: action.payload
};
default: // Don't forget your default case
break;
}
然后是這樣的:
changeAppData({
...state,
testValue: 'Updated Test Value Here'
})
編輯:我剛剛意識到UPDATE_APP_DATA我做的案例和你的完全一樣setAppData。哈哈,好吧,所以你只需要第一個案例。但是我可能不會這樣做,因為您每次都需要傳入整個物件。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/524780.html
