我有几个按钮作为路径。每次改变路线时,我都想确保激活的按钮发生了变化。

有没有办法在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]);

}

用钩子

其他回答

我刚刚处理了这个问题,所以我将把我的解答作为其他答案的补充。

这里的问题是useEffect并没有像您希望的那样工作,因为调用只在第一次呈现之后才被触发,因此存在不必要的延迟。 如果您使用一些状态管理器,如redux,您很可能会在屏幕上看到闪烁,因为存储中存在持续的状态。

你真正想要的是使用uselayouteeffect,因为它会立即被触发。

所以我写了一个小的实用函数,我把它放在和路由器相同的目录中:

export const callApis = (fn, path) => {
    useLayoutEffect(() => {
      fn();
    }, [path]);
};

我从组件HOC中调用它,如下所示:

callApis(() => getTopicById({topicId}), path);

path是使用withRouter时在match对象中传递的道具。

我真的不赞成手动地听/不听历史。 这只是我的看法。

withRouter,历史。listen,和useEffect (React Hooks)一起工作得很好:

import React, { useEffect } from 'react'
import { withRouter } from 'react-router-dom'

const Component = ({ history }) => {
    useEffect(() => history.listen(() => {
        // do something on route change
        // for my example, close a drawer
    }), [])

    //...
}

export default withRouter(Component)

侦听器回调将在路由更改时触发,并返回历史记录。listen是一个关闭处理程序,可以很好地与useEffect一起使用。

import { useHistory } from 'react-router-dom';

const Scroll = () => {
  const history = useHistory();

  useEffect(() => {
    window.scrollTo(0, 0);
  }, [history.location.pathname]);

  return null;
}

对于React路由器v6和React钩子, 你需要使用useLocation而不是useHistory,因为它已被弃用

import { useLocation } from 'react-router-dom'
import { useEffect } from 'react'

export default function Component() {

const history = useLocation();

   useEffect(() => {
    console.log('> Router', history.pathname)      
}, [history.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}`)
})