extraReducer 中的 redux-toolkit 状态更改不会启动重新渲染
redux-toolkit state change in extraReducer does not initiate rerender
我正在尝试同时注销和清除商店,所以点击我发送这个:
dispatch({type: PURGE, key: 'root', result: () => { } });
Redux persist 捕获它,并报告清除存储。伟大的。
在另一个减速器中,我捕获了该调度,并像这样删除了我的访问令牌:
import { PURGE } from 'redux-persist/es/constants';
const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
setAccessToken(state: AuthState, action: PayloadAction<Auth>): void {
state.accessToken = action.payload.accessToken;
state.expiresIn = action.payload.expiresIn;
},
},
extraReducers: {
[PURGE]: (state: AuthState, action: string): void => {
state.accessToken = initialState.accessToken;
state.expiresIn = initialState.expiresIn;
},
},
});
实际上调用了 PURGE reducer,并修改了状态,但仍然没有重新渲染。所以 redux 不能接受它。但是根据文档,Redux 工具包使用 Proxy 对象作为状态并进行比较以查看它是否被修改。
我尝试过的事情:
state = initialState;
和
state = { ...initialState };
没用。存储工作,并保存数据,其他操作工作。我该如何进行?
编辑:进一步调试显示我自己的减速器在 redux-persist 减速器之前被调用,并且 redux-logger 报告我的减速器根本没有改变状态。
结果证明这是解决方案:
extraReducers: {
[PURGE]: (state: UserState, action: string): UserState => ({
...state,
...initialState,
}),
},
我不明白为什么,根据 documentation:
,修改状态对象应该也可以
To make things easier, createReducer uses immer to let you write
reducers as if they were mutating the state directly. In reality, the
reducer receives a proxy state that translates all mutations into
equivalent copy operations.
我遇到了类似的问题(不是重新渲染),今天遇到了这个问题:
好像你不能完全替换状态对象。
发件人:https://redux-toolkit.js.org/usage/immer-reducers
Sometimes you may want to replace the
entire existing state, either because you've loaded some new data, or
you want to reset the state back to its initial value.
WARNING A common mistake is to try assigning state = someValue
directly. This will not work! This only points the local state
variable to a different reference. That is neither mutating the
existing state object/array in memory, nor returning an entirely new
value, so Immer does not make any actual changes.
const initialState = []
const todosSlice = createSlice({
name: 'todos',
initialState,
reducers: {
brokenTodosLoadedReducer(state, action) {
// ❌ ERROR: does not actually mutate or return anything new!
state = action.payload
},
fixedTodosLoadedReducer(state, action) {
// ✅ CORRECT: returns a new value to replace the old one
return action.payload
},
correctResetTodosReducer(state, action) {
// ✅ CORRECT: returns a new value to replace the old one
return initialState
},
},
})
所以
state = initialState;
会是
return initialState;
我正在尝试同时注销和清除商店,所以点击我发送这个:
dispatch({type: PURGE, key: 'root', result: () => { } });
Redux persist 捕获它,并报告清除存储。伟大的。 在另一个减速器中,我捕获了该调度,并像这样删除了我的访问令牌:
import { PURGE } from 'redux-persist/es/constants';
const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
setAccessToken(state: AuthState, action: PayloadAction<Auth>): void {
state.accessToken = action.payload.accessToken;
state.expiresIn = action.payload.expiresIn;
},
},
extraReducers: {
[PURGE]: (state: AuthState, action: string): void => {
state.accessToken = initialState.accessToken;
state.expiresIn = initialState.expiresIn;
},
},
});
实际上调用了 PURGE reducer,并修改了状态,但仍然没有重新渲染。所以 redux 不能接受它。但是根据文档,Redux 工具包使用 Proxy 对象作为状态并进行比较以查看它是否被修改。
我尝试过的事情:
state = initialState;
和
state = { ...initialState };
没用。存储工作,并保存数据,其他操作工作。我该如何进行?
编辑:进一步调试显示我自己的减速器在 redux-persist 减速器之前被调用,并且 redux-logger 报告我的减速器根本没有改变状态。
结果证明这是解决方案:
extraReducers: {
[PURGE]: (state: UserState, action: string): UserState => ({
...state,
...initialState,
}),
},
我不明白为什么,根据 documentation:
,修改状态对象应该也可以To make things easier, createReducer uses immer to let you write reducers as if they were mutating the state directly. In reality, the reducer receives a proxy state that translates all mutations into equivalent copy operations.
我遇到了类似的问题(不是重新渲染),今天遇到了这个问题: 好像你不能完全替换状态对象。
发件人:https://redux-toolkit.js.org/usage/immer-reducers
Sometimes you may want to replace the entire existing state, either because you've loaded some new data, or you want to reset the state back to its initial value.
WARNING A common mistake is to try assigning state = someValue directly. This will not work! This only points the local state variable to a different reference. That is neither mutating the existing state object/array in memory, nor returning an entirely new value, so Immer does not make any actual changes.
const initialState = []
const todosSlice = createSlice({
name: 'todos',
initialState,
reducers: {
brokenTodosLoadedReducer(state, action) {
// ❌ ERROR: does not actually mutate or return anything new!
state = action.payload
},
fixedTodosLoadedReducer(state, action) {
// ✅ CORRECT: returns a new value to replace the old one
return action.payload
},
correctResetTodosReducer(state, action) {
// ✅ CORRECT: returns a new value to replace the old one
return initialState
},
},
})
所以
state = initialState;
会是
return initialState;