React 6.2无需useHistory获取上一URL路径实现Material UI动态面包屑
解决方案:React Router 6.x 中获取上一URL路径构建面包屑
方案1:自定义路由历史记录栈
React Router 6 不再直接提供访问完整历史栈的API,但可以通过useLocation钩子监听路由变化,手动维护一个历史路径数组:
import { useState, useEffect } from 'react'; import { useLocation } from 'react-router-dom'; export function usePreviousPath() { const [previousPaths, setPreviousPaths] = useState([]); const location = useLocation(); useEffect(() => { // 排除重复的同路径跳转,避免栈中冗余数据 if (previousPaths[previousPaths.length - 1] !== location.pathname) { setPreviousPaths(prev => [...prev, location.pathname]); } }, [location.pathname]); // 返回栈中倒数第二个路径,即上一页面路径 return previousPaths.length > 1 ? previousPaths[previousPaths.length - 2] : null; }
在面包屑组件中直接调用这个自定义钩子:
import { usePreviousPath, useNavigate } from 'react-router-dom'; function Breadcrumb() { const prevPath = usePreviousPath(); const navigate = useNavigate(); return ( <div className="breadcrumb"> {prevPath && ( <span onClick={() => navigate(prevPath)} className="breadcrumb-link"> {prevPath.split('/').pop() || '首页'} </span> )} {/* 当前页面面包屑节点 */} <span className="current-page">当前页面</span> </div> ); }
方案2:利用导航状态传递上一路径
如果是通过React Router的navigate方法跳转的页面,可以在跳转时主动携带当前路径作为状态参数:
// 跳转发起组件 import { useNavigate, useLocation } from 'react-router-dom'; function SomeComponent() { const navigate = useNavigate(); const location = useLocation(); const goToTargetPage = () => { // 跳转时将当前路径存入state navigate('/target-page', { state: { from: location.pathname } }); }; }
然后在目标页面的面包屑组件中,从location.state取出上一路径:
import { useLocation, useNavigate } from 'react-router-dom'; function Breadcrumb() { const location = useLocation(); const navigate = useNavigate(); const prevPath = location.state?.from; return ( <div className="breadcrumb"> {prevPath && ( <span onClick={() => navigate(-1)} className="breadcrumb-link"> {prevPath.split('/').pop()} </span> )} <span className="current-page">目标页面</span> </div> ); }
方案3:监听浏览器popstate事件(原生API)
如果需要处理浏览器前进/后退按钮触发的路由变化,可以结合原生popstate事件与sessionStorage记录历史路径:
import { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; export function useBrowserPreviousPath() { const [prevPath, setPrevPath] = useState(null); const navigate = useNavigate(); useEffect(() => { // 初始化时记录当前路径到存储 const initPath = window.location.pathname; let pathHistory = JSON.parse(sessionStorage.getItem('routeHistory')) || []; if (pathHistory[pathHistory.length - 1] !== initPath) { pathHistory.push(initPath); sessionStorage.setItem('routeHistory', JSON.stringify(pathHistory)); } const handlePopState = () => { pathHistory = JSON.parse(sessionStorage.getItem('routeHistory')) || []; // 弹出当前路径,剩余最后一个即为上一路径 pathHistory.pop(); setPrevPath(pathHistory[pathHistory.length - 1]); sessionStorage.setItem('routeHistory', JSON.stringify(pathHistory)); }; window.addEventListener('popstate', handlePopState); return () => window.removeEventListener('popstate', handlePopState); }, []); return prevPath; }
注意:该方案依赖浏览器sessionStorage,若用户清空存储或打开新标签页,历史记录会丢失,适合对历史持久化要求不高的场景。
内容的提问来源于stack exchange,提问作者Adv3012
相关产品推荐
相关产品推荐

