如何使用react-router v4检测路线更改?

时间:2018-07-21 20:35:32

标签: reactjs react-router react-router-dom

我需要检测是否发生了路由更改,以便可以将变量更改为true。

我已经仔细研究了以下问题:
1. https://github.com/ReactTraining/react-router/issues/3554
2. How to listen to route changes in react router v4?
3. Detect Route Change with react-router

他们都没有为我工作。发生路线更改时,有没有一种清晰的方法来调用函数。

6 个答案:

答案 0 :(得分:15)

一种方法是使用withRouter高阶组件。

Live demo (单击超链接以更改路线并在显示的控制台中查看结果)

  

您可以通过withRouter高阶组件访问历史对象的属性和最接近的匹配项。每当呈现时,withRouter都会将更新的匹配项,位置和历史道具传递给包装的组件。

https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/withRouter.md

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

class App extends Component {
    componentDidUpdate(prevProps) {
        if (this.props.location.pathname !== prevProps.location.pathname) {
            console.log('Route change!');
        }
    }
    render() {
        return (
            <div className="App">
                ...routes
            </div>
        );
    }
}

export default withRouter(props => <App {...props}/>);

另一个使用url参数的示例:

如果您要将配置文件路由从/profile/20更改为/profile/32

您的路线被定义为/profile/:userId

componentDidUpdate(prevProps) {
    if (this.props.match.params.userId !== prevProps.match.params.userId) {
        console.log('Route change!');
    }
}

答案 1 :(得分:8)

使用React Hooks,它应该很简单:

useEffect(() => {
    const { pathname } = location;
    console.log('New path:', pathname);
}, [location.pathname]);

通过在第二个数组参数中传递location.pathname,意味着您要说使用useEffect仅在location.pathname更改时重新运行。

带有代码源:https://codesandbox.io/s/detect-route-path-changes-with-react-hooks-dt16i

的实时示例

答案 2 :(得分:3)

React Router v5现在通过钩子自动检测路由更改。以下是the example from the team

import { Switch, useLocation } from 'react-router'

function usePageViews() {
  let location = useLocation()

  useEffect(
    () => {
      ga.send(['pageview', location.pathname])
    },
    [location]
  )
}

function App() {
  usePageViews()
  return <Switch>{/* your routes here */}</Switch>
}

每次URL更改时,此示例都会向Google Analytics(分析)(ga)发送“页面视图”。

答案 3 :(得分:0)

如何在您的应用程序状态下跟踪历史对象的长度?每当遍历新路线时,由反应路由器提供的历史对象的长度就会增加。参见下图。

enter image description here

ComponentDidMountComponentWillUnMount检查: enter image description here

答案 4 :(得分:0)

使用基于组件的体系结构。那么,为什么我们不遵守这个规则?

您可以看到DEMO

每个页面必须由HOC包装,这将自动检测页面的变化。

首页

import React from "react";
import { NavLink } from "react-router-dom";
import withBase from "./withBase";

const Home = () => (
  <div>
    <p>Welcome Home!!!</p>
    <NavLink to="/login">Go to login page</NavLink>
  </div>
);

export default withBase(Home);

withBase HOC

import React from "react";

export default WrappedComponent =>
  class extends React.Component {
    componentDidMount() {
      this.props.handleChangePage();
    }

    render() {
      return <WrappedComponent />;
    }
  };

答案 5 :(得分:0)

当组件被指定为<form> <div> <label for="file">Choose file to upload</label> <input type="file" id={fileName} /> </div> <div> <!--Should be something along the lines of `this.handleSubmit` rather than `this.print`, but you get the idea--> <button onClick={this.print}>Submit</button> </div> </form> 的{​​{1}}属性时,React Router 4(RR4)向其传递了一些附加属性:<Route>component和{{1 }}。

然后,您应该使用match生命周期方法在更新前后比较location个对象(记住ES对象比较规则)。由于位置对象是不可变的,因此它们将永远不会匹配。即使您导航到相同的位置。

history
需要在未指定为任何Route的componentDidUpdate属性的任意组件中访问这些属性时,应使用

location。请确保将您的应用包装在 componentDidUpdate(newProps) { if (this.props.location !== newProps.location) { this.handleNavigation(); } } 中,因为它提供了所有必需的API,否则这些方法将仅在withRouter中包含的组件中起作用。

在某些情况下,用户决定通过导航按钮而不是浏览器中的专用界面来重新加载页面。但是这样的比较:

component

将使其变为不可能。