我正在开发一个 React 打字稿应用程序。我已经实现了 redux-persist 但似乎数据没有保存在 localstorage 中。我的代码如下。尽快回复。
它在开始时正在补水,但不会从本地存储中保存或检索数据。
/**
* Create the store with dynamic reducers
*/
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
import { createInjectorsEnhancer } from 'redux-injectors';
import createSagaMiddleware from 'redux-saga';
import { createReducer } from './reducers';
// imports for presist store
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
// persist config
const persistConfig = {
key: 'root',
// blacklist: ['extra'],
// whitelist: ['auth'],
// stateReconciler: autoMergeLevel2,
storage,
}
export function configureAppStore() {
const reduxSagaMonitorOptions = {};
const sagaMiddleware = createSagaMiddleware(reduxSagaMonitorOptions);
const { run: runSaga } = sagaMiddleware;
// Create the store with saga middleware
const middlewares = [sagaMiddleware];
const enhancers = [
createInjectorsEnhancer({
createReducer,
runSaga,
}),
];
const persistedReducer = persistReducer(persistConfig, createReducer());
const store = configureStore({
reducer: persistedReducer,
middleware: [...getDefaultMiddleware(), ...middlewares],
devTools: process.env.NODE_ENV !== 'production',
enhancers,
});
const persistor = persistStore(store);
return {store, persistor};
}
/**
* Combine all reducers in this file and export the combined reducers.
*/
import { combineReducers } from '@reduxjs/toolkit';
import { InjectedReducersType } from 'utils/types/injector-typings';
/**
* Merges the main reducer with the router state and dynamically injected reducers
*/
export function createReducer(injectedReducers: InjectedReducersType = {}) {
// Initially we don't have any injectedReducers, so returning identity function to avoid the error
if (Object.keys(injectedReducers).length === 0) {
return state => state;
} else {
return combineReducers({
...injectedReducers,
});
}
}
import { selectAuthLoading } from './selectors';
import { PayloadAction } from '@reduxjs/toolkit';
import { createSlice } from 'utils/@reduxjs/toolkit';
import { useInjectReducer, useInjectSaga } from 'utils/redux-injectors';
import { authSaga } from './saga';
import { AuthState } from './types';
export const initialState: AuthState = {
isLoggedIn: false,
token: '',
user: {
name: '',
email: '',
},
extras: {
screenLoading: false,
authLoading: false,
},
};
const slice = createSlice({
name: 'auth',
initialState,
reducers: {
loginUser(
state,
action: PayloadAction<{
email: string;
password: string;
}>,
) {},
setLoggedIn(state, action: PayloadAction<boolean>) {
state.isLoggedIn = action.payload;
},
setToken(state, action: PayloadAction<string>) {
state.token = action.payload;
},
setAuthLoading(state, action: PayloadAction<boolean>) {
state.extras.authLoading = action.payload;
},
},
});
export const { actions: authActions } = slice;
export const useAuthSlice = () => {
useInjectReducer({ key: slice.name, reducer: slice.reducer });
useInjectSaga({ key: slice.name, saga: authSaga });
return { actions: slice.actions };
};
/**
* index.tsx
*
* This is the entry file for the application
*/
import 'react-app-polyfill/ie11';
import 'react-app-polyfill/stable';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
// Use consistent styling
import 'sanitize.css/sanitize.css';
// Import root app
import { App } from 'app';
import { HelmetProvider } from 'react-helmet-async';
import { configureAppStore } from 'store/configureStore';
import reportWebVitals from 'reportWebVitals';
// Redux Persist imports
import { PersistGate } from 'redux-persist/integration/react';
// Initialize languages
import './locales/i18n';
// Components
import { ScreenLoader } from './app/components/ScreenLoader';
const { store, persistor } = configureAppStore();
const MOUNT_NODE = document.getElementById('root') as HTMLElement;
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<PersistGate loading={<ScreenLoader />} persistor={persistor}>
<HelmetProvider>
<React.StrictMode>
<App />
</React.StrictMode>
</HelmetProvider>
</PersistGate>
</Provider>
</React.StrictMode>,
MOUNT_NODE,
);
// Hot reloadable translation json files
if (module.hot) {
module.hot.accept(['./locales/i18n'], () => {
// No need to render the App again because i18next works with the hooks
});
}
reportWebVitals();
import axios from 'axios';
import { take, call, put, select, takeLatest } from 'redux-saga/effects';
import { authActions as actions } from '.';
import { API_URL } from './../../../utils/constants';
import { User } from './../../../API';
import { ToastContainer, toast } from 'react-toastify';
// Logging in the user
// function* loginUserSaga(payload: {email: string, password: string}){
function* loginUserSaga(action: any) {
try {
yield put({ type: actions.setAuthLoading.type, payload: true });
const response = yield call(User.getUser, action.payload);
if (response && response.data || response.data === '') {
yield put({ type: actions.setAuthLoading.type, payload: false });
yield put({type: actions.setToken.type, payload: response.data.data.accessToken});
toast(response.data.message, {
type:
response.data.message.toLowerCase() === 'success'
? 'success'
: 'warning',
});
} else {
yield put({ type: actions.setAuthLoading.type, payload: false });
toast('Unknown error!', {
type: 'error',
});
}
} catch (error) {
yield put({ type: actions.setAuthLoading.type, payload: false });
toast(error.message, {
type: 'error',
});
}
}
// Setting logged in user
function* setLoggedSaga(payload: any) {
yield put({ type: actions.setAuthLoading.type, payload: true });
console.log(payload);
yield put({ type: actions.setAuthLoading.type, payload: false });
}
export function* authSaga() {
yield takeLatest(actions.setLoggedIn.type, setLoggedSaga);
yield takeLatest(actions.loginUser.type, loginUserSaga);
}