react-router 重新加回跳转拦截功能详解
作者:马格纳斯
前言
路由的跳转拦截,在一些表单页中尤为常见。场景:用户输入了一些信息后但未提交,为了防止用户误点击某个跳转链接导致所填的表单信息丢失,跳转之前会弹出一个提示,如 “信息未提交,请确认是否离开” 等字样。
事件经过
在 react-router v6
之前有提供一个 <Prompt />
组件来拦截路由的跳转。而在 v6
中却不支持此功能了!社区一片哀嚎,经查在 v6
实验阶段是有此功能的,但在 v6.0.0 beta-7
中删除了此功能。在这个 issue 链接 中每个人都强烈要求需要此功能,但官方回复会在不久的将来添加,有需要的可以回退到 v5
,基本所有人都表示 👎。然而这一等就是一年多,很多人这期间在 issue 中表示非常失望,这个不久的将来
到底还有没有了?终于在 v6.7.0
重新加入了此功能,原来不久的将来约等于一年。
v6 之前的版本如何拦截
在你需要拦截的页面添加 <Prompt />
组件,我们在输入框中有值,且进行跳转页面时进行拦截。当 when
为 true 时,执行跳转会触发拦截操作,message
为提示。
function Home() { const [value, setValue] = useState(""); return ( <div> <Link to="/about" /> <input value={value} onChange={e => setValue(e.target.value)} /> <Prompt when={!!value} message="确认要离开吗" /> </div> ); }
弹出的提示进行自定义,when
可以设置为一个函数,参数为 location
和 action(行为)
,返回 string | boolean
。返回 string
或 true
就是直接离开了。
function Home() { const [value, setValue] = useState(""); const history = useHistory(); return ( <div> <Link to="/about" /> <input value={value} onChange={(e) => setValue(e.target.value)} /> <Prompt when={!!value} message={(location, action) => { Modal.confirm({ message: "确定要离开吗", onOk: () => { history.push(location.pathname); }, }); return false; }} /> </div> ); }
v6.7.0+ 如何拦截
在这个版本中提供了一个 unstable_useBlocker
钩子,但在文档中是没有的(艹),需要自己去 examples 里找。useBlocker
传入的参数类似于上面的 when
。
useBlocker 的参数为 boolean
或 函数返回 boolean
,函数的类型如下:
(args: { currentLocation: Location; nextLocation: Location; historyAction: HistoryAction; }) => boolean
blocker
里的 state
为 blocked
时,说明当前正在进行拦截,此时弹出一个 Modal,点击确认就是进行跳转,点击取消就是不跳转。blocked
中还能获取到 location
,可以根据你的需要来使用。
import { unstable_useBlocker as useBlocker } from "react-router-dom"; function Home() { const [value, setValue] = useState(""); const blocker = useBlocker(!!value); useEffect(() => { if (blocker.state === "blocked") { Modal.confirm({ message: "确认离开吗", onOk: () => { blocker.proceed?.(); }, onCancel: () => { blocker.reset?.(); }, }); } }, [blocker]); return ( <div> <Link to="/about" /> <input value={value} onChange={(e) => setValue(e.target.value)} /> </div> ); }
吐槽
最后,就在这里吐槽一下吧。文档很烂,不支持搜索!且 v6.4
的后续版本中加入了很多 api,例如 action
和 loader
的概念,跟数据请求有关。但是我觉得很难用,路由库就应该只专注路由,应该跟它们的 remix
框架的发展有关吧。官方的权限控制例子也是不好用,很麻烦。下个文章会写在 v6 中如何优雅简单的管理权限。
以上就是react-router 重新加回跳转拦截功能详解的详细内容,更多关于react router 跳转拦截的资料请关注脚本之家其它相关文章!