React JS或React Router中获取用户访问起始URL的方法(React v16)
嘿,针对你在React v16项目里想获取用户访问的起始URL(也就是用户从哪个页面跳转过来的)这个需求,我整理了几种实用的方案,分场景来说明:
1. 不使用React Router的原生浏览器方案
如果你的项目没有用React Router,或者想直接获取浏览器层面的来源信息,可以用浏览器提供的document.referrer属性。它会返回用户跳转过来的前一个页面的完整URL。
代码示例
你可以在组件的useEffect钩子中获取这个值:
import { useEffect, useState } from 'react'; function CurrentPage() { const [referrer, setReferrer] = useState(''); useEffect(() => { // 获取来源URL const incomingReferrer = document.referrer; setReferrer(incomingReferrer || '用户直接访问/无来源'); }, []); return <div>用户来源: {referrer}</div>; }
注意事项
- 如果用户是直接在地址栏输入URL、通过书签访问,或者浏览器隐私设置禁用了Referrer,
document.referrer会返回空字符串。 - 当从HTTPS页面跳转到HTTP页面时,部分浏览器也会清空这个值,这是出于安全考虑。
2. 使用React Router的方案(v5/v6都适用)
如果你的项目用了React Router,除了原生方法外,还可以通过路由的状态传递或者全局监听来追踪来源,灵活性更高。
方式一:跳转时手动传递来源信息
在跳转的时候,通过路由的state属性把当前页面的URL传递到目标页面,这种方式适合你能控制跳转触发的场景。
React Router v5 示例
// 来源页面(比如HomePage) import { Link } from 'react-router-dom'; function HomePage() { return ( <Link to={{ pathname: '/profile', // 把当前页面的URL作为来源存入state state: { from: window.location.href } }} > 查看个人资料 </Link> ); } // 目标页面(ProfilePage) import { useLocation } from 'react-router-dom'; function ProfilePage() { const location = useLocation(); // 从state中取出来源,没有的话默认显示直接访问 const from = location.state?.from || '直接访问'; return <div>用户来自: {from}</div>; }
React Router v6 示例
v6的API略有变化,用useNavigate代替useHistory,但state传递逻辑一致:
// 来源页面跳转逻辑 import { useNavigate } from 'react-router-dom'; function HomePage() { const navigate = useNavigate(); const goToProfile = () => { navigate('/profile', { state: { from: window.location.href } }); }; return <button onClick={goToProfile}>查看个人资料</button>; } // 目标页面获取来源 import { useLocation } from 'react-router-dom'; function ProfilePage() { const location = useLocation(); const from = location.state?.from || '直接访问'; return <div>用户来自: {from}</div>; }
注意事项
- 路由的
state是存在内存里的,如果用户刷新页面,state会丢失。如果需要持久化,可以把来源信息存在localStorage或者sessionStorage里。
方式二:全局监听路由变化记录上一页
如果需要全局追踪每个页面的来源,可以在路由的根组件里监听路由变化,记录上一个访问的路径。
React Router v5 示例
import { useEffect, useState } from 'react'; import { useHistory } from 'react-router-dom'; import { Route, Switch } from 'react-router-dom'; function App() { const history = useHistory(); const [previousPath, setPreviousPath] = useState(null); useEffect(() => { // 监听路由变化 const unlisten = history.listen((location, action) => { // 只有当路由是PUSH操作时,记录上一个路径 if (action === 'PUSH') { setPreviousPath(history.location.pathname); } }); // 组件卸载时取消监听 return unlisten; }, [history]); // 你可以把previousPath存入全局状态(比如Context、Redux),供所有组件使用 return ( <div className="App"> <Switch> {/* 你的路由配置 */} <Route path="/home" component={HomePage} /> <Route path="/profile" component={ProfilePage} /> </Switch> </div> ); }
React Router v6 示例
v6用useNavigationType和useLocation来实现监听:
import { useEffect, useState } from 'react'; import { useLocation, useNavigationType, Routes, Route } from 'react-router-dom'; function App() { const location = useLocation(); const navigationType = useNavigationType(); const [previousPath, setPreviousPath] = useState(null); useEffect(() => { if (navigationType === 'PUSH') { setPreviousPath(location.pathname); } }, [location, navigationType]); // 同样可以把previousPath存入全局状态 return ( <div className="App"> <Routes> <Route path="/home" element={<HomePage />} /> <Route path="/profile" element={<ProfilePage />} /> </Routes> </div> ); }
内容的提问来源于stack exchange,提问作者Rizal Ibnu
相关产品推荐
相关产品推荐

