React路由,使用useLocation()和useEffect()实现路由监控
发布于 作者:苏南大叔 来源:程序如此灵动~React Router@v5
之后的版本,取消了useHistory()
这个钩子。在ReactRouter@v6
版本中,其有关导航的部分功能,使用新的钩子useNavigate()
代替。而history.listen()
这部分功能,在新版本的react router
中该如何实现呢?这就是本文要讨论的内容。
苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。本文测试环境:nodejs@20.18.0
,create-react-app@5.0.1
,react-router-dom@6.27.0
,react@18.3.1
。
旧版history.listen()主要功能
history.listen()
老版本的代码,这里苏南大叔就不列举了。看名字也能猜出相关功能来,就是对react
程序的浏览历史的监控功能,或者说是location
的变化情况。
当然,这里需要特别强调的是:并不是浏览器的历史记录功能,两者还是有比较大的区别的。react
的location
并不等同于window
的location
。
新的实现方案
在新的版本中,实际上可以使用useLocation()
+ useEffect()
,组合获得历史记录。核心组合如下:
import React, { useEffect } from "react";
import { useLocation } from "react-router-dom";
const location = useLocation();
useEffect(() => {
console.log(location);
//...
}, [location]);
参考文章:
浏览历史组件
苏南大叔这里实现了一个组件,实现的主要功能就是对location
的监控。可以用于对路由相关功能的调试,比如<Link to=''>
等功能的记录等。
主要代码如下:
import React, { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
function HistoryBar() {
const location = useLocation();
const [historyRecords, setHistoryRecords] = useState([]);
useEffect(() => {
if (location.state === null || location.state === "null") {
location.state = "";
}
setHistoryRecords([location].concat(historyRecords));
}, [location]);
return (
<div>
<table>
<tbody>
{historyRecords.map((record, index) => (
<tr key={index}>
<td>{record.key}</td>
<td>{record.pathname}</td>
<td>{record.search}</td>
<td>{JSON.stringify(record.state, "", 2)}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
export default HistoryBar;
调用举例:
import { NavLink, Outlet } from "react-router-dom";
import HistoryBar from "./HistoryBar";
const Layout = () => {
return (
<>
<div className="bar">
<NavLink to="/" state={{ id: 1, title: "首页" }}>
首页
</NavLink>
<NavLink to="/s">S页面</NavLink>
<NavLink to="/n">N页面</NavLink>
</div>
<HistoryBar></HistoryBar>
<Outlet></Outlet>
</>
);
};
当然,本文的重要前提是上述代码,包裹在一个router
里面,这个道理大家都明白。这里就不详细描述了,可以参考苏南的相关文章:
可能遇到的问题
eslint
对上面的代码,可能会提示信息:
React Hook useEffect has a missing dependency: 'historyRecords'. Either include it or remove the dependency array. You can also do a functional update 'setHistoryRecords(h => ...)' if you only need 'historyRecords' in the 'setHistoryRecords' call
苏南大叔觉得它的提示有道理,但是,从这个组件的设计上来说,数据的驱动并不允许其它地方来主动修改这个值historyRecords
。所以,并没有这个依赖需求。
结语
苏南大叔的React
相关经验文章,请参考下面的链接:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。