React项目中SessionStorage存储特定用户的初始化状态问题求助
解决React银行项目中SessionStorage与用户状态同步问题
问题根源
- 页面刷新后
users状态重置为空数组,导致基于users查找的specificUser丢失 - 直接在
useState初始值中读取SessionStorage时,users尚未加载完成,执行find会因数组为空报错 - 当前
DataProvider中直接执行sessionStorage.setItem,会在每次组件渲染时触发,逻辑冗余且易出问题
解决方案步骤
1. 重构DataProvider的状态管理
- 初始化
users时优先从SessionStorage恢复数据,兜底为空数组 - 用
useEffect监听specificUsername和users的变化,仅当两者都有效时才更新SessionStorage - 维护独立的
specificUser状态,避免每次渲染都执行find操作
修改后的DataProvider代码:
import { useContext, createContext, useState, useEffect } from "react"; import axios from "axios"; import { useTranslation } from "react-i18next"; export const DataContext = createContext(); export const useDataProvider = () => useContext(DataContext); const DataProvider = ({ children }) => { // 初始化users:优先从SessionStorage读取,无则为空数组 const [users, setUsers] = useState(() => { const savedUsers = sessionStorage.getItem("users"); return savedUsers ? JSON.parse(savedUsers) : []; }); const [specificUsername, setSpecificUsername] = useState(""); const [specificUser, setSpecificUser] = useState(null); // 当specificUsername或users变化时,查找并更新特定用户,同步到SessionStorage useEffect(() => { if (specificUsername && users.length > 0) { const foundUser = users.find(user => user.username === specificUsername); if (foundUser) { setSpecificUser(foundUser); sessionStorage.setItem("key", JSON.stringify(foundUser)); } } }, [specificUsername, users]); // 保存users到SessionStorage(如果users是从接口获取的,可在获取后调用) const saveUsersToStorage = (newUsers) => { setUsers(newUsers); sessionStorage.setItem("users", JSON.stringify(newUsers)); }; const isUsernameExist = (username) => { return users.some(user => user.username === username); }; // 其他方法如loanMoney、changeLanguage等保持原有逻辑 const loanMoney = (username, amount) => { // 你的贷款逻辑 }; const changeLanguage = (key) => { // 你的多语言逻辑 }; return ( <DataContext.Provider value={{ users, setUsers: saveUsersToStorage, specificUser, specificUsername, setSpecificUsername, isUsernameExist, loanMoney, changeLanguage }} > {children} </DataContext.Provider> ); }; export default DataProvider;
2. 调整SignInPage逻辑
无需大幅修改,确保调用setSpecificUsername后,DataProvider的useEffect会自动同步用户到SessionStorage:
import React, { useState } from "react"; import Authentication from "../../components/authentication_sign/AuthenticationSign"; import { useDataProvider } from "../../context/Data"; import { useNavigate } from "react-router-dom"; const SignInPage = () => { const [error, setError] = useState(false); const navigate = useNavigate(); const { setSpecificUsername, isUsernameExist } = useDataProvider(); const handleClick = (data) => { const { username, password } = data; if (username === "Admin" && password === "1111") return navigate("/admin"); if (!isUsernameExist(username)) return setError("用户不存在"); setSpecificUsername(username); navigate("/user/current-account"); }; return <Authentication userError={error} onClick={handleClick} text={"登录"} />; }; export default SignInPage;
3. 优化Loan页面的用户读取逻辑
增加空值判断,避免SessionStorage中无数据时解构报错,同时优先从Context获取用户:
import React, { useState } from "react"; import { useNavigate } from "react-router-dom"; import { useDataProvider } from "../../context/Data"; import UserPage from "./UserPage"; // 假设你有这个组件 import Input from "./Input"; // 假设你有这个组件 const Loan = () => { const navigate = useNavigate(); const { loanMoney, changeLanguage, specificUser } = useDataProvider(); // 优先用Context中的specificUser,兜底从SessionStorage读取 const user = specificUser || JSON.parse(sessionStorage.getItem('key')) || {}; const { username, income = 0 } = user; const [error, setError] = useState(""); const inpData = [{ name: "price", type: "number" }]; const maxLoan = Math.floor((income * 70) / 100); const handleClick = (data) => { if (!username) return setError("请先登录"); if (data.price > maxLoan) return setError("申请已被拒绝"); loanMoney(username, Number(data.price)); navigate("/user/current-account"); }; return ( <UserPage> <Input text={'贷款'} inpNumber={1} inpData={inpData} error={error} onClick={handleClick} rules={{ required: "请填写", minLength: { value: 2, message: "至少输入2位" } }} /> <h2>{changeLanguage('max loan')} {maxLoan} ₪</h2> </UserPage> ); }; export default Loan;
关键说明
- 用
useState的初始化函数读取SessionStorage,确保只在组件首次挂载时执行一次 - 通过
useEffect监听状态变化,避免不必要的SessionStorage操作 - 在Loan页面增加空值兜底,防止用户未登录或SessionStorage数据丢失时报错
内容的提问来源于stack exchange,提问作者Lior98
相关产品推荐
相关产品推荐

