React Router中页面跳转前如何在localStorage存储数据?
解决方案:SPA路由跳转前存储数据到localStorage
问题核心
你遇到的问题根源有两个:
beforeunload事件仅在浏览器刷新、关闭标签页/窗口时触发,React Router的SPA内部路由跳转不会触发该事件。- 你之前的
useBeforeUnload代码中,useCallback的依赖数组为空,导致闭包捕获的formData、id、revisionNo始终是初始值,即使触发事件也存不了正确数据。
方案一:监听路由跳转(推荐,适配SPA内部跳转)
利用React Router的useLocation和useEffect,在组件卸载(即用户路由跳离当前页面)时执行数据存储:
import { useLocation, useEffect } from 'react-router-dom'; // 在你的表单组件内 const location = useLocation(); useEffect(() => { // 组件卸载时触发(路由跳转离开当前页) return () => { // localStorage只能存字符串,对象/数组需转JSON const storedData = JSON.stringify(formData); localStorage.setItem(`formCreation${id}${revisionNo}`, storedData); }; }, [id, revisionNo, formData]); // 必须补全所有依赖,确保捕获最新值
方案二:结合路由拦截(需用户确认跳转时使用)
如果需要在用户离开前弹出确认提示(比如表单未完成编辑),可以用React Router v6+的useBlocker,同时在拦截逻辑中存储数据:
import { useBlocker } from 'react-router-dom'; // 在组件内 const blocker = useBlocker((transition) => { // 先存储数据 const storedData = JSON.stringify(formData); localStorage.setItem(`formCreation${id}${revisionNo}`, storedData); // 允许路由跳转 transition.proceed(); }); // 若需要提示确认,可搭配usePrompt import { usePrompt } from 'react-router-dom'; usePrompt({ message: '表单未保存,确定要离开吗?', when: !!formData.isDirty // 仅当表单有修改时触发提示 });
方案三:修复useBeforeUnload(处理浏览器刷新/关闭)
如果同时需要处理浏览器刷新、关闭的场景,补全useCallback的依赖项即可:
import { useBeforeUnload } from 'react-router-dom'; import { useCallback } from 'react'; useBeforeUnload( useCallback(() => { const storedData = JSON.stringify(formData); localStorage.setItem(`formCreation${id}${revisionNo}`, storedData); }, [id, revisionNo, formData]) // 补全依赖,确保拿到最新数据 );
注意:此方案仅处理浏览器级别的卸载,仍需搭配方案一覆盖SPA内部跳转场景。
关键注意点
localStorage仅支持存储字符串,若formData是对象/数组,必须用JSON.stringify()转换,读取时用JSON.parse()解析。- 所有依赖项必须加入
useEffect或useCallback的依赖数组,避免闭包导致的旧数据问题。
内容的提问来源于stack exchange,提问作者user121443
相关产品推荐
相关产品推荐

