我有一个简单的reducer/context系统来存储状态。一切都很好,只是我不能单独更新字段而不影响其他字段的状态。
问题是,当我更改其中一个AppData
字段时,其他字段变为空白。我不知道我做错了什么,我希望能够更新单个值,同时保留其他字段的值。
例如:如果我只更新appData.headerTitle
值,那么appData.testValue
和appData.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
谢谢!
我不知道该在这里尝试什么。。。
每次进行更改时,都会发送一个有效载荷,该有效载荷是一个具有ONE属性的对象,例如在App.tsx
第22行中,它是一个带有一个属性headerTitle
的对象。
所以AppReducer.tsx
第9行中的这个对象覆盖了整个当前状态,所以如果有任何其他属性,它们将被覆盖并消失。
为了解决这个问题,我建议你分散这个有效载荷,用数据保存以前的字段:
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;
};
您的changeAppData
案例出现了一些问题。另外,感觉代码中缺少了一些部分,例如,在useContext钩子中没有返回changeAppData
fn。但据我所见,当您遇到changeAppData
情况时,所有三个appData
值都将是相同的,因为它们都设置为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
。您需要从reducer中获取状态对象,然后将该对象与update键/属性一起传入。
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
完全一样。。哈哈,好吧,你只需要第一个病例。然而,我可能不会这样做,因为每次都需要传入整个对象。