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;
原因分析
- React组件状态(包括
useImmer管理的userToken)存储在内存中,页面刷新时整个应用会重新初始化,userToken会被重置为初始的空字符串,导致Token丢失。 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
相关产品推荐
相关产品推荐

