如何在React-Redux中通过Local Storage获取合并Reducer中的状态值(如TOKEN)
Hey there! Let's tackle your problem step by step—first addressing how to fetch values like TOKEN from localStorage, then fixing a critical issue in your reducers that might be causing unexpected behavior with state persistence.
1. Accessing TOKEN (or Other Combined Reducer State) from LocalStorage
Since you're saving the entire Redux state to localStorage with your saveToLocalStorage function, the stored state matches the structure created by combineReducers:
{ authReducer: { /* auth state */ }, roomReducer: { /* room state */ } }
To get the TOKEN value, you just need to parse the saved state and navigate to the correct reducer key:
// Retrieve and parse the saved state const persistedState = localStorage.getItem("persistantState"); const parsedState = persistedState ? JSON.parse(persistedState) : null; // Extract the TOKEN const token = parsedState ? parsedState.authReducer.TOKEN : null;
You can use this snippet anywhere you need to access the token directly from localStorage (though in most cases, you should prefer using useSelector to get it from the Redux store instead of reading localStorage directly).
2. Fixing Reducer Immutability Issues (Critical!)
Looking at your reducer code, you're directly modifying the existing state object (e.g., state["ACTIVEFRIEND"] = null;). This violates Redux's requirement for immutable state updates—Redux relies on state references changing to detect updates, so mutating the original state will break state persistence and cause unexpected UI behavior.
Here's how to rewrite your reducers correctly using the spread operator (...) to return new state objects:
Updated Auth Reducer Example
import authTypes from "./Types"; const authForm = { IS_AUTHENTICATED: false, AUTH_SUCCESS: false, USERNAME: "AnonymousUser", TOKEN: null, }; const authReducer = (state = authForm, action) => { switch (action.type) { case authTypes.SIGN_IN_SUCCESS: return { ...state, // Copy existing state IS_AUTHENTICATED: true, AUTH_SUCCESS: true, USERNAME: action.username, TOKEN: action.token }; case authTypes.SIGN_IN_FAIL: return { ...state, IS_AUTHENTICATED: false, AUTH_SUCCESS: false, USERNAME: "AnonymousUser", TOKEN: null }; // Repeat this pattern for all other cases... case authTypes.SIGN_OUT_FAIL: return { ...state, IS_AUTHENTICATED: localStorage.getItem("IS_AUTHENTICATED") === "true", // Note: localStorage stores strings! AUTH_SUCCESS: false, USERNAME: localStorage.getItem("USERNAME"), TOKEN: localStorage.getItem("TOKEN") }; default: return state; } }; export default authReducer;
Updated Room Reducer Example
import backendTypes from "./Types"; const roomForm = { ACTIVEFRIEND: null, ROOMS: null, ROOM: null, }; const roomReducer = (state = roomForm, action) => { switch (action.type) { case backendTypes.GET_ROOMS_SUCCESS: return { ...state, ACTIVEFRIEND: null, ROOMS: action.allRooms, ROOM: null }; case backendTypes.GET_ROOM_SUCCESS: return { ...state, ACTIVEFRIEND: action.activeFriend, ROOMS: JSON.parse(localStorage.getItem("ROOMS")), // Parse since localStorage stores strings ROOM: action.activeRoom }; // Repeat this pattern for all other cases... default: return state; } }; export default roomReducer;
Key Notes:
- Always return a new object instead of mutating the original state.
- When reading boolean values from localStorage, remember it stores everything as strings—so you'll need to convert them back to booleans (e.g.,
localStorage.getItem("IS_AUTHENTICATED") === "true"). - When reading objects/arrays from localStorage, parse them with
JSON.parse()(since you saved them withJSON.stringify()).
3. Bonus: Prefer useSelector for Accessing State in Components
Instead of reading localStorage directly in your components, use React-Redux's useSelector hook to get the token from the store:
import { useSelector } from 'react-redux'; function MyComponent() { const token = useSelector(state => state.authReducer.TOKEN); // Use the token here... }
This is the standard Redux pattern and ensures you're always using the most up-to-date state.
内容的提问来源于stack exchange,提问作者Shend Tytynxhiu

