我有几个按钮作为路径。每次改变路线时,我都想确保激活的按钮发生了变化。
有没有办法在react路由器v4中监听路由变化?
我有几个按钮作为路径。每次改变路线时,我都想确保激活的按钮发生了变化。
有没有办法在react路由器v4中监听路由变化?
当前回答
import React, { useEffect } from 'react';
import { useLocation } from 'react-router';
function MyApp() {
const location = useLocation();
useEffect(() => {
console.log('route has been changed');
...your code
},[location.pathname]);
}
用钩子
其他回答
您应该使用history v4 lib。
这里的例子
history.listen((location, action) => {
console.log(`The current URL is ${location.pathname}${location.search}${location.hash}`)
console.log(`The last navigation action was ${action}`)
})
使用useEffect钩子,可以在不添加侦听器的情况下检测路由更改。
import React, { useEffect } from 'react';
import { Switch, Route, withRouter } from 'react-router-dom';
import Main from './Main';
import Blog from './Blog';
const App = ({history}) => {
useEffect( () => {
// When route changes, history.location.pathname changes as well
// And the code will execute after this line
}, [history.location.pathname]);
return (<Switch>
<Route exact path = '/' component = {Main}/>
<Route exact path = '/blog' component = {Blog}/>
</Switch>);
}
export default withRouter(App);
对于功能组件,请尝试使用props.location中的useEffect。
import React, {useEffect} from 'react';
const SampleComponent = (props) => {
useEffect(() => {
console.log(props.location);
}, [props.location]);
}
export default SampleComponent;
要在上面的基础上展开,您需要获取history对象。如果您正在使用BrowserRouter,您可以导入withRouter并使用高阶组件(HoC)包装您的组件,以便通过道具访问历史对象的属性和函数。
import { withRouter } from 'react-router-dom';
const myComponent = ({ history }) => {
history.listen((location, action) => {
// location is an object like window.location
console.log(action, location.pathname, location.state)
});
return <div>...</div>;
};
export default withRouter(myComponent);
唯一需要注意的是,使用throuter和大多数其他访问历史的方法似乎会污染道具,因为它们将对象解构到其中。
正如其他人所说,这已经被react路由器暴露的钩子所取代,并且它有内存泄漏。如果你在一个函数组件中注册监听器,你应该通过useEffect来做,然后在函数的返回中取消注册。
我刚刚处理了这个问题,所以我将把我的解答作为其他答案的补充。
这里的问题是useEffect并没有像您希望的那样工作,因为调用只在第一次呈现之后才被触发,因此存在不必要的延迟。 如果您使用一些状态管理器,如redux,您很可能会在屏幕上看到闪烁,因为存储中存在持续的状态。
你真正想要的是使用uselayouteeffect,因为它会立即被触发。
所以我写了一个小的实用函数,我把它放在和路由器相同的目录中:
export const callApis = (fn, path) => {
useLayoutEffect(() => {
fn();
}, [path]);
};
我从组件HOC中调用它,如下所示:
callApis(() => getTopicById({topicId}), path);
path是使用withRouter时在match对象中传递的道具。
我真的不赞成手动地听/不听历史。 这只是我的看法。