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

Next.js13中React Context页面刷新后值重置问题求助

问题分析与解决:Next.js 13中Context状态刷新后丢失

问题根源

React Context的状态仅存储在客户端内存中,页面刷新时整个React应用会重新初始化,Context里的状态会回到定义的默认值,因此之前通过API设置的数据会丢失。另外你在子组件中直接执行await fetchApi(),会导致组件每次渲染都重复发起API请求,还可能触发不必要的状态更新。

解决方法

要保留Context状态,需将数据持久化到本地存储(如localStorage/sessionStorage),在Context初始化时从存储读取数据,状态更新时同步写入存储。同时修复子组件的API调用逻辑,避免重复请求。

步骤1:修改Context Provider,集成持久化逻辑

更新contextProvider.ts,在初始化状态时从localStorage读取值,并用useEffect监听状态变化同步到存储:

"use client";

import React, { useEffect } from "react";
import { createContext, Dispatch, SetStateAction } from "react";

interface IChildrenProp {
  children: React.ReactNode;
}

interface IAppContext {
  userId: number;
  setUserId: Dispatch<SetStateAction<number>>;
  userName: string;
  setUserName: Dispatch<SetStateAction<string>>;
  userEmail: string;
  setUserEmail: Dispatch<SetStateAction<string>>;
  userRole: string;
  setUserRole: Dispatch<SetStateAction<string>>;
}

export const AppContext = createContext<IAppContext>({
  userId: 0,
  setUserId: (): number => 0,
  userName: "",
  setUserName: () => "",
  userEmail: "",
  setUserEmail: () => "",
  userRole: "",
  setUserRole: () => "",
});

export const ContextProvider: React.FC<IChildrenProp> = ({ children }) => {
  // 从localStorage读取初始值,无数据则用默认值
  const [userId, setUserId] = React.useState<number>(() => {
    const saved = localStorage.getItem("userId");
    return saved ? parseInt(saved, 10) : 0;
  });
  const [userName, setUserName] = React.useState<string>(() => {
    return localStorage.getItem("userName") || "";
  });
  const [userEmail, setUserEmail] = React.useState<string>(() => {
    return localStorage.getItem("userEmail") || "";
  });
  const [userRole, setUserRole] = React.useState<string>(() => {
    return localStorage.getItem("userRole") || "";
  });

  // 状态变化时同步到localStorage
  useEffect(() => {
    localStorage.setItem("userId", userId.toString());
    localStorage.setItem("userName", userName);
    localStorage.setItem("userEmail", userEmail);
    localStorage.setItem("userRole", userRole);
  }, [userId, userName, userEmail, userRole]);

  return (
    <AppContext.Provider
      value={{
        userId,
        setUserId,
        userName,
        setUserName,
        userEmail,
        setUserEmail,
        userRole,
        setUserRole,
      }}
    >
      {children}
    </AppContext.Provider>
  );
};

步骤2:修复子组件的API调用逻辑

将API请求放到useEffect中,仅在初始状态下发起请求,避免重复调用:

"use client"

import React, { useEffect, useContext } from "react";
import { AppContext } from "./contextProvider";

const ChildComponent = () => {
  const { userId, setUserId, userName, setUserName } = useContext(AppContext);

  console.log(userId, userName);

  useEffect(() => {
    // 仅当userId为默认值时,才发起API请求
    if (userId === 0) {
      const fetchData = async () => {
        const result = await fetchApi();
        if (result) {
          setUserId(result.id);
          setUserName(result.username);
        }
      };
      fetchData();
    }
  }, [userId, setUserId, setUserName]);

  return <div>子组件内容</div>;
};

export default ChildComponent;

补充说明

  • 若存储敏感信息,建议使用sessionStorage(关闭标签页后数据自动清除),或结合后端token验证,页面刷新时先验证token再重新获取用户数据。
  • localStorage仅支持字符串存储,数字类型需手动转换(如userId存为字符串,读取时转数字)。

内容的提问来源于stack exchange,提问作者Abhishek Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 09:23:17