Ani*_*ska 17 local-storage reactjs redux redux-toolkit
我想将 isAuthenticated 状态保留在本地存储中,因此刷新页面后,用户将登录。我尝试直接在 localStorage 中将其设置为 true/false 并将 redux 中状态的初始值设置为此value,但它总是将其设置为 true。
这是我的 redux 商店
import { createSlice, configureStore } from '@reduxjs/toolkit';
//MOVEMENTS (doesn't work yet)
const initialMovementsState = {
movements: [],
};
const movementsSlice = createSlice({
name: 'movements',
initialState: initialMovementsState,
reducers: {
add(state) {
//nothing yet
},
decrement(state) {
//nothing yet
},
},
});
//LOGGING IN/OUT
const initialAuthState = {
isAuthenticated: false,
};
const authSlice = createSlice({
name: 'auth',
initialState: initialAuthState,
reducers: {
login(state) {
state.isAuthenticated = true;
},
logout(state) {
state.isAuthenticated = false;
},
},
});
//STORE CONFIGURATION
const store = configureStore({
reducer: {
movements: movementsSlice.reducer,
auth: authSlice.reducer,
},
});
export const movementsActions = movementsSlice.actions;
export const authActions = authSlice.actions;
export default store;
Run Code Online (Sandbox Code Playgroud)
我找到的所有答案都仅与 redux 相关,而不是与 redux 工具包相关,而且我对 redux 还很陌生,所以我迷路了。
Lin*_*ste 44
2022 年 10 月更新createListenerMiddleware:您还可以在 1.8 及更高版本中使用 redux-toolkit ,如本答案中所述。
更改localStorage是一种副作用,因此您不想在您的减速器中进行更改。减速器应该始终没有副作用。处理此问题的一种方法是使用自定义中间件。
我们的中间件在每个操作被调度后都会被调用。如果操作是login或logout那么我们将更改该localStorage值。否则我们什么也不做。无论哪种方式,我们都会将操作传递给链中的下一个中间件return next(action)。
redux-toolkit 和 vanilla redux 中间件的唯一区别是我们如何检测login和logout操作。使用 redux-toolkit,动作创建器功能包括一个有用的match()功能,我们可以使用它,而不必查看type. 我们知道,action如果为 true,则 an 是登录操作login.match(action)。所以我们的中间件可能看起来像这样:
const authMiddleware = (store) => (next) => (action) => {
if (authActions.login.match(action)) {
// Note: localStorage expects a string
localStorage.setItem('isAuthenticated', 'true');
} else if (authActions.logout.match(action)) {
localStorage.setItem('isAuthenticated', 'false');
}
return next(action);
};
Run Code Online (Sandbox Code Playgroud)
您将在函数中将中间件添加到您的商店configureStore。Redux-toolkit默认包含一些中间件,支持 thunk、不变性检查和可序列化检查。现在,您middleware根本没有在商店中设置该属性,因此您将获得所有默认值。我们希望确保在添加自定义中间件时保留默认值。
该middleware属性可以定义为一个由 redux-toolkit 函数调用的函数getDefaultMiddleware。如果您愿意,这允许您设置默认中间件的选项,同时还可以添加我们自己的中间件。我们将按照文档示例编写:
const store = configureStore({
reducer: {
movements: movementsSlice.reducer,
auth: authSlice.reducer,
},
// Note: you can include options in the argument of the getDefaultMiddleware function call.
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(authMiddleware)
});
Run Code Online (Sandbox Code Playgroud)
不要这样做,因为它将删除所有默认中间件
const store = configureStore({
reducer: {
movements: movementsSlice.reducer,
auth: authSlice.reducer,
},
middleware: [authMiddleware]
});
Run Code Online (Sandbox Code Playgroud)
我们可以通过匹配所有 auth操作来简化我们的中间件。String.prototype.startsWith()我们通过使用上的方法来做到这一点(类似于文档部分中使用 的action.type示例)。addMatcher.endswith()
这里我们通过在改变next(action) 之前执行来找到下一个状态localStorage。我们将该localStorage值设置为切片返回的新状态auth。
const authMiddleware = (store) => (next) => (action) => {
const result = next(action);
if ( action.type?.startsWith('auth/') ) {
const authState = store.getState().auth;
localStorage.setItem('auth', JSON.stringify(authState))
}
return result;
};
Run Code Online (Sandbox Code Playgroud)
或者您可以使用redux-persist包,它会为您完成此操作。
Ani*_*ska 19
与此同时,我已经编写了运动逻辑,并希望将所有状态保留在本地存储中。Linda Paiste 的回答非常有帮助(并且对如此长而直接的答案表示赞赏!),但我在将本地存储发送回我的 redux 状态方面遇到了困难。这是工作解决方案:
import { createSlice, configureStore } from '@reduxjs/toolkit';
import dummyItems from '../helpers/dummyItems';
const initialMovementsState = {
movements: dummyItems,
};
const movementsSlice = createSlice({
name: 'movements',
initialState: initialMovementsState,
reducers: {
add(state, action) {
state.movements = [action.payload, ...state.movements];
},
delete(state, action) {
const id = action.payload;
state.movements = state.movements.filter(mov => mov.id !== id);
},
},
});
//AUTHORIZATION
const initialAuthState = {
isAuthenticated: false,
};
const authSlice = createSlice({
name: 'auth',
initialState: initialAuthState,
reducers: {
login(state) {
state.isAuthenticated = true;
},
logout(state) {
state.isAuthenticated = false;
},
},
});
//MIDDLEWARE
const localStorageMiddleware = ({ getState }) => {
return next => action => {
const result = next(action);
localStorage.setItem('applicationState', JSON.stringify(getState()));
return result;
};
};
const reHydrateStore = () => {
if (localStorage.getItem('applicationState') !== null) {
return JSON.parse(localStorage.getItem('applicationState')); // re-hydrate the store
}
};
//STORE CONFIGURATION
const store = configureStore({
reducer: {
movements: movementsSlice.reducer,
auth: authSlice.reducer,
},
preloadedState: reHydrateStore(),
middleware: getDefaultMiddleware =>
getDefaultMiddleware().concat(localStorageMiddleware),
});
export const movementsActions = movementsSlice.actions;
export const authActions = authSlice.actions;
export default store;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
31904 次 |
| 最近记录: |