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

React页面刷新后userToken状态丢失问题排查与解决

问题:React登录后刷新页面Token丢失的原因及解决方案

我用React实现了用户登录获取Token的功能,首次登录跳转后功能正常,但刷新/employer/jobs页面时,userToken会变为空值。相关代码如下:

Login.jsx

const Login = () => {
  const { setUserToken } = useContext(AppContext);

  const submitForm = async (values) => {
    postUserLogin(values)
      .then((response) => {
        const { token } = response.data;
        setUserToken(token);
        setApiError({ status: '', error: '' });
        navigate('/employer/jobs');
      })
      .catch((err) => {
        setUserToken('');
      });
  };

  return (<>...</>);
};
export default Login;

EmployerJob.jsx

const EmployerJob = () => {
  const { employerJobs, setEmployerJobs, userToken} = useContext(AppContext);
  const [paginatorInfo, setPaginatorInfo] = useState({});

  useEffect(() => {
    const fetchData = async () => {
      const res = await getEmployerJobList(userToken);
      if (res.status === 200) {
        const { paginator, items: jobs } = res.data;
        setPaginatorInfo(paginator);
        setEmployerJobs(jobs);
      }
    };
    fetchData();
  }, []);

  return (
    <div className="text-light my-4">
      <span>Length: {paginatorInfo.count}</span>
      {employerJobs.length > 0 ? 
        employerJobs.map((job, index) => (
          <p key={index}>{job.salary}</p>
        )) : 
        <p>No Job!</p>
      }
    </div>
  );
};
export default EmployerJob;

appContext.jsx

import {createContext} from 'react';

export const AppContext = createContext({
    userToken:'',
    setUserToken:()=>{},
    employerJobs:[],
    setEmployerJobs:()=>{},
});

App.js

const App= ()=> {
  const [userToken, setUserToken] = useImmer('');
  const [employerJobs, setEmployerJobs] = useImmer([]);
  
  return(
    <AppContext.Provider value={{
      userToken,
      setUserToken,
      employerJobs,
      setEmployerJobs,
    }}>
    <div className='App'>
        <Navbar/>
        <Routes>
          <Route path='/employer/login' element={<Login/>} />
          <Route path='/employer/jobs' element={<EmployerJob/>}/>
          <Route path="*" element={<NotFound/>}/>
        </Routes>
    </div>
    </AppContext.Provider>
  );
}
export default App;

原因分析

  1. React组件状态(包括useImmer管理的userToken)存储在内存中,页面刷新时整个应用会重新初始化,userToken会被重置为初始的空字符串,导致Token丢失。
  2. EmployerJob组件的useEffect依赖项为空数组,即使刷新后Token恢复,也无法触发重新请求数据,页面依然无法获取正确的职位列表。

解决方案

1. 实现Token持久化存储

修改App.js,将Token存储到浏览器localStorage中,初始化时从localStorage读取,变化时同步更新:

import { useImmer, useEffect } from 'react';

const App= ()=> {
  // 从localStorage读取初始化Token,无值则为空
  const [userToken, setUserToken] = useImmer(localStorage.getItem('userToken') || '');
  const [employerJobs, setEmployerJobs] = useImmer([]);

  // 监听Token变化,同步到localStorage
  useEffect(() => {
    localStorage.setItem('userToken', userToken);
  }, [userToken]);
  
  return(
    <AppContext.Provider value={{
      userToken,
      setUserToken,
      employerJobs,
      setEmployerJobs,
    }}>
    <div className='App'>
        <Navbar/>
        <Routes>
          <Route path='/employer/login' element={<Login/>} />
          <Route path='/employer/jobs' element={<EmployerJob/>}/>
          <Route path="*" element={<NotFound/>}/>
        </Routes>
    </div>
    </AppContext.Provider>
  );
}
export default App;

2. 调整EmployerJob的请求触发条件

将userToken添加到useEffect依赖数组,确保Token变化时重新请求数据,同时增加空Token判断避免无效请求:

useEffect(() => {
  const fetchData = async () => {
    if (!userToken) return; // 空Token不发起请求
    const res = await getEmployerJobList(userToken);
    if (res.status === 200) {
      const { paginator, items: jobs } = res.data;
      setPaginatorInfo(paginator);
      setEmployerJobs(jobs);
    }
  };
  fetchData();
}, [userToken]); // 添加userToken作为依赖

内容的提问来源于stack exchange,提问作者Javad-M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 03:28:18