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

页面刷新后useState丢失localStorage数据,如何解决?

解决页面刷新后localStorage数据无法正常读取的问题

你的代码存在几个核心问题,导致刷新后state无法正确获取localStorage中的数据,下面是具体修复方案:

1. 直接用localStorage初始化state

组件挂载时,useState的初始值应该直接从localStorage读取,而不是等到useEffect执行后再设置。这样初始渲染阶段就能拿到数据,不用依赖异步的state更新。

示例修改:

const [userId, setUserId] = useState<string>(
  JSON.parse(localStorage.getItem("userId") as string) || ""
);
const [results, setResults] = useState<boolean>(localStorage.length > 0);
const [studentEnglishResults, setStudentEnglishResults] = useState<{
  [key: string]: string;
}>(
  JSON.parse(localStorage.getItem("englishAnswers") as string) || {}
);
const [englishResults, setEnglishResults] = useState<string[]>(
  Object.keys(JSON.parse(localStorage.getItem("englishAnswers") as string) || {})
);

2. 修复useEffect里的异步state更新问题

你原代码中在useEffect里设置完state后立刻console.log,但React的state更新是异步的,此时打印的还是旧值。另外setEnglishResults(Object.keys(studentEnglishResults))里的studentEnglishResults还是初始空对象,因为setStudentEnglishResults还未完成更新。

正确做法是直接使用从localStorage读取的原始值:

useEffect(() => {
  const storedUserId = JSON.parse(localStorage.getItem("userId") as string);
  const storedEnglishAnswers = JSON.parse(localStorage.getItem("englishAnswers") as string);
  
  if (localStorage.length > 0) {
    setUserId(storedUserId);
    setResults(true);
    setStudentEnglishResults(storedEnglishAnswers);
    setEnglishResults(Object.keys(storedEnglishAnswers));
  } else {
    setResults(false);
    setUserId("");
    setStudentEnglishResults({});
    setEnglishResults([]);
  }

  // 要打印最新值直接用本地变量
  console.log(storedUserId);
  console.log(storedEnglishAnswers);
  console.log(Object.keys(storedEnglishAnswers));
}, []);

3. 给依赖userId的useEffect添加正确依赖项

原代码中查找用户的useEffect没有依赖userId,刷新时userId还是初始空字符串,导致找不到用户。需要把userId加入依赖数组,这样userId更新后会重新执行查找逻辑:

useEffect(() => {
  const userFound = users.find((user) => user.userId === userId);
  if (userFound) {
    console.log(userFound);
  } else {
    console.log("user not found");
  }
}, [userId]);

完整修改后的代码

const Admin = () => {
  const { adminId } = useParams();
  const navigate = useNavigate();

  // 直接从localStorage初始化state
  const [userId, setUserId] = useState<string>(
    JSON.parse(localStorage.getItem("userId") as string) || ""
  );
  const [results, setResults] = useState<boolean>(localStorage.length > 0);
  const [studentEnglishResults, setStudentEnglishResults] = useState<{
    [key: string]: string;
  }>(
    JSON.parse(localStorage.getItem("englishAnswers") as string) || {}
  );
  const [englishResults, setEnglishResults] = useState<string[]>(
    Object.keys(JSON.parse(localStorage.getItem("englishAnswers") as string) || {})
  );

  const adminUser = adminUsers.find(
    (adminUser) => adminUser.adminId === adminId
  );

  useEffect(() => {
    if (adminUser?.adminId !== adminId) {
      navigate("/");
      return;
    }
  }, [adminUser, adminId, navigate]);

  useEffect(() => {
    const storedUserId = JSON.parse(localStorage.getItem("userId") as string);
    const storedEnglishAnswers = JSON.parse(localStorage.getItem("englishAnswers") as string);
    
    if (localStorage.length > 0) {
      setUserId(storedUserId);
      setResults(true);
      setStudentEnglishResults(storedEnglishAnswers);
      setEnglishResults(Object.keys(storedEnglishAnswers));
    } else {
      setResults(false);
      setUserId("");
      setStudentEnglishResults({});
      setEnglishResults([]);
    }
  }, []);

  useEffect(() => {
    const userFound = users.find((user) => user.userId === userId);
    if (userFound) {
      console.log(userFound);
    } else {
      console.log("user not found");
    }
  }, [userId]);

  const generateResult = () => {};

  const clearResult = () => {
    localStorage.clear();
    // 清空localStorage后同步更新state
    setResults(false);
    setUserId("");
    setStudentEnglishResults({});
    setEnglishResults([]);
  };

  const backToLogin = () => {
    navigate("/");
  };

  return (
    <>
      <div className="bg-gray-400 mx-auto w-3/4 p-3 mt-5">
        <p className="capitalize font-serif text-center">
          <span className="font-bold uppercase text-white text-2xl">
            student result checker
          </span>
        </p>
      </div>
      <div className="my-10 flex justify-center gap-3 text-white">
        <button
          type="button"
          className="btn bg-green-500"
          onClick={generateResult}
        >
          Generate Results
        </button>

        <button type="button" className="btn bg-blue-500" onClick={backToLogin}>
          Login
        </button>
      </div>
      {results ? (
        <div>
          <div className="shadow-md shadow-gray-500 w-2/4 mx-auto p-5">
            <p className="text-2xl text-gray-500">Answers selected by: </p>
            <table className="table-auto border-collapse border w-full">
              <thead>
                <tr>
                  <th className="text-left">Question</th>
                  <th className="text-left">Answer</th>
                </tr>
              </thead>
              <tbody>
                {englishResults.map((item, index) => {
                  return (
                    <tr key={index}>
                      <td className="">{item}</td>
                      <td>{studentEnglishResults[item]}</td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
          <div className="w-2/4 mx-auto mt-5 p-5">
            <button
              type="button"
              className="btn bg-red-600 text-white"
              onClick={clearResult}
            >
              Clear Results
            </button>
          </div>
        </div>
      ) : (
        <div className="w-2/4 bg-gray-400 p-5 mx-auto rounded-md">
          <p className="text-4xl text-white text-center">
            There is no result to display
          </p>
        </div>
      )}
    </>
  );
};

export default Admin;

额外说明:

  • 给第一个useEffect补充了adminUser、adminId、navigate依赖,避免ESLint警告
  • 在clearResult函数中,清空localStorage后同步更新了所有state,保证UI和数据状态一致
  • 修复了mt-50的错误(Tailwind无该类),改为mt-5

内容的提问来源于stack exchange,提问作者Misbahu Abubakar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 15:55:13