使用对象作为有效负载更新切片中的状态
Updating a state in a slice, with object as a payload
我有这个切片:
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { IAuthState } from '../../types';
const initialState: IAuthState = {
isAuthenticated: false,
profile: null,
};
export const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
setAuthState(state, { payload }: PayloadAction<IAuthState>) {
console.log({ payload });
state = payload;
},
},
});
export const { setAuthState } = authSlice.actions;
export const authReducer = authSlice.reducer;
这是标准样板切片。
问题是如果我这样做,我的状态不会更新。 Redux devtools 说没有变化。我的有效载荷是这样的:
{
isAuthenticated: true,
profile: {...} // big object
}
但是如果我这样分配:
reducers: {
setAuthState(state, { payload }: PayloadAction<IAuthState>) {
state.isAuthenticated = payload.isAuthenticated;
state.profile = payload.profile
},
},
它更新状态。这是为什么?以及如何批量更新整个状态?
如何更新整个状态?
无论是使用 Redux Toolkit 的切片还是基本的 Redux reducer,如果您想替换整个状态,只需 return 一个全新的值。
setAuthState(state, { payload }: PayloadAction<IAuthState>) {
return payload; // replaces the whole state
},
为什么 returning 而不是赋值,更新状态?
state = payload;
state
是一个本地标识符,重新分配它在函数之外没有任何作用。尽管在 JavaScript、object references are passed by value 中,所以在函数内部改变 state
对象也会在函数外部引用的任何地方改变同一个对象。
Redux Toolkit simplifies state updates by letting devs mutate the passed state
object, which is usually prohibited with immutable states,就像在 vanilla Redux 或 React state 中一样。
It uses the Immer library internally, which lets you write code that "mutates" some data, but actually applies the updates immutably. This makes it effectively impossible to accidentally mutate state in a reducer.
在 reducer 中返回一个新对象只会替换整个状态并忽略代理对象。
无论如何,如果我这样做 state.profile=payload.profile
,会发生这种情况吗?
是的,显式改变每个属性(利用 RTK 对 Immer 的使用)会做同样的事情,但需要更多代码。尽管如果负载有更多的属性,它们将不会包含在切片的状态中。
这可能是您想要的,如果不明确将不需要的数据添加到减速器,任何不需要的数据都不会进入状态。所以说清楚一点也不是坏事。
如果您拥有很多属性,那么维护起来可能会很烦人。
setAuthState(state, { payload }) {
state.isAuthenticated = payload.isAuthenticated;
state.profile = payload.profile
state.thing = payload.thing
state.stuff = payload.stuff
state.foo = payload.foo
state.bar = payload.bar
// etc...
},
如果我想要整个负载而不替换不相关的状态值怎么办?
如果 payload
变长,但您不想替换整个状态,您可以做的是 return 一个新对象从传播当前状态和有效负载。
setAuthState(state, { payload }) {
return {
...state,
...payload,
};
},
我有这个切片:
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { IAuthState } from '../../types';
const initialState: IAuthState = {
isAuthenticated: false,
profile: null,
};
export const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
setAuthState(state, { payload }: PayloadAction<IAuthState>) {
console.log({ payload });
state = payload;
},
},
});
export const { setAuthState } = authSlice.actions;
export const authReducer = authSlice.reducer;
这是标准样板切片。
问题是如果我这样做,我的状态不会更新。 Redux devtools 说没有变化。我的有效载荷是这样的:
{
isAuthenticated: true,
profile: {...} // big object
}
但是如果我这样分配:
reducers: {
setAuthState(state, { payload }: PayloadAction<IAuthState>) {
state.isAuthenticated = payload.isAuthenticated;
state.profile = payload.profile
},
},
它更新状态。这是为什么?以及如何批量更新整个状态?
如何更新整个状态?
无论是使用 Redux Toolkit 的切片还是基本的 Redux reducer,如果您想替换整个状态,只需 return 一个全新的值。
setAuthState(state, { payload }: PayloadAction<IAuthState>) {
return payload; // replaces the whole state
},
为什么 returning 而不是赋值,更新状态?
state = payload;
state
是一个本地标识符,重新分配它在函数之外没有任何作用。尽管在 JavaScript、object references are passed by value 中,所以在函数内部改变 state
对象也会在函数外部引用的任何地方改变同一个对象。
Redux Toolkit simplifies state updates by letting devs mutate the passed state
object, which is usually prohibited with immutable states,就像在 vanilla Redux 或 React state 中一样。
It uses the Immer library internally, which lets you write code that "mutates" some data, but actually applies the updates immutably. This makes it effectively impossible to accidentally mutate state in a reducer.
在 reducer 中返回一个新对象只会替换整个状态并忽略代理对象。
无论如何,如果我这样做 state.profile=payload.profile
,会发生这种情况吗?
是的,显式改变每个属性(利用 RTK 对 Immer 的使用)会做同样的事情,但需要更多代码。尽管如果负载有更多的属性,它们将不会包含在切片的状态中。
这可能是您想要的,如果不明确将不需要的数据添加到减速器,任何不需要的数据都不会进入状态。所以说清楚一点也不是坏事。
如果您拥有很多属性,那么维护起来可能会很烦人。
setAuthState(state, { payload }) {
state.isAuthenticated = payload.isAuthenticated;
state.profile = payload.profile
state.thing = payload.thing
state.stuff = payload.stuff
state.foo = payload.foo
state.bar = payload.bar
// etc...
},
如果我想要整个负载而不替换不相关的状态值怎么办?
如果 payload
变长,但您不想替换整个状态,您可以做的是 return 一个新对象从传播当前状态和有效负载。
setAuthState(state, { payload }) {
return {
...state,
...payload,
};
},