You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 12:21:49