react-router-dom useNavigate跳转外部链接路径错误如何解决
问题根源
useNavigate是react-router-dom提供的站内路由专用跳转API,默认会将传入的所有地址参数识别为站内路径,不会自动识别带协议的外部绝对地址,因此传入外部地址时会直接将其拼接到当前站点域名后,生成错误的跳转路径。
另外原始代码还存在两个隐性问题:
useEffect不支持直接传入async函数作为回调:async函数返回值是Promise,而useEffect要求返回值为清理函数,该写法会引发潜在的内存泄漏风险- 跳转地址取值错误:接口返回的数据存储在响应对象
response中,直接从axios实例上取redirectLink拿不到后端返回的真实地址
解决方案
跳转前先对目标地址做类型判断,站内路由走useNavigate逻辑,外部地址用原生浏览器跳转API处理即可。
- 先封装地址判断、格式化的工具方法
// 判断是否为外部地址 const isExternalUrl = (url) => { // 匹配http/https协议开头、协议相对路径开头的地址 return /^(https?:\/\/|\/\/)/.test(url); }; // 格式化地址,兼容后端返回不带协议头的外部域名场景 const formatUrl = (url) => { // 识别类似xxx.com这类不带协议、也不是/开头的内部路径的地址,自动补全https协议头 if (/^[\w-]+\.[\w.-]+/.test(url) && !/^(https?:\/\/|\/\/|\/)/.test(url)) { return `https://${url}`; } return url; };
- 修正页面跳转逻辑,修复useEffect的async写法问题
import { useEffect } from "react"; import { useNavigate } from "react-router-dom"; import axios from "axios"; function RedirectPage() { const navigate = useNavigate(); useEffect(() => { // useEffect内部定义异步函数,避免直接传async回调的问题 const getRedirectTarget = async () => { const res = await axios.get("你的后端接口地址"); const targetUrl = formatUrl(res.data.redirectLink); if (isExternalUrl(targetUrl)) { // 外部地址用原生location跳转,replace模式可避免返回时回到中转页造成死循环 window.location.replace(targetUrl); // 若需要保留跳转前的页面历史,可改用 window.location.href = targetUrl return; } // 内部路由正常走react-router跳转逻辑 navigate(targetUrl, { replace: true }); }; getRedirectTarget(); }, [navigate]); return <div>跳转中,请稍候...</div>; } // 工具函数定义 const isExternalUrl = (url) => /^(https?:\/\/|\/\/)/.test(url); const formatUrl = (url) => { if (/^[\w-]+\.[\w.-]+/.test(url) && !/^(https?:\/\/|\/\/|\/)/.test(url)) { return `https://${url}`; } return url; };
注意事项
- 外部地址跳转优先使用
window.location.replace(),相比直接给window.location.href赋值,该方法会替换当前浏览历史条目,避免用户点击返回键时反复回到中转跳转页 - 若后端返回的地址规则有特殊格式(比如自定义协议、特殊路由前缀),可以在
isExternalUrl判断逻辑中补充对应的匹配规则即可
内容的提问来源于stack exchange,提问作者rel1x
相关产品推荐
相关产品推荐

