如何在路由器v4中侦听路由变化?

Kas*_*per 105 react-router-v4

我有几个按钮充当路线.每次更改路线时,我都要确保激活的按钮发生变化.

有没有办法在路由器v4中侦听路由更改?

小智 146

withRouter用来得到location道具.当组件由于新路由而更新时,我检查值是否更改:

@withRouter
class App extends React.Component {

  static propTypes = {
    location: React.PropTypes.object.isRequired
  }

  // ...

  componentDidUpdate(prevProps) {
    if (this.props.location !== prevProps.location) {
      this.onRouteChanged();
    }
  }

  onRouteChanged() {
    console.log("ROUTE CHANGED");
  }

  // ...
  render(){
    return <Switch>
        <Route path="/" exact component={HomePage} />
        <Route path="/checkout" component={CheckoutPage} />
        <Route path="/success" component={SuccessPage} />
        // ...
        <Route component={NotFound} />
      </Switch>
  }
}
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你

  • 在路由器v4中使用'this.props.location.pathname'. (13认同)
  • @ledfusion我正在做同样的事情,并使用`withRouter`,但是却出现错误`您不应在&lt;Router&gt;`之外使用&lt;Route&gt;或withRouter()。我在上面的代码中没有看到任何`&lt;Router /&gt;`组件。那么它是如何工作的呢? (3认同)

Mug*_*gen 78

v5.1 引入了有用的钩子 useLocation

https://reacttraining.com/blog/react-router-v5-1/#uselocation

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

function usePageViews() {
  let location = useLocation()

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

function App() {
  usePageViews()
  return <Switch>{/* your routes here */}</Switch>
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,因为我遇到了错误:“无法读取 useLocation 处未定义的属性‘位置’”。您需要确保 useLocation() 调用不在将路由器放入树中的同一组件中:[请参阅此处](https://github.com/ReactTraining/react-router/issues/7015) (21认同)

Sam*_*ter 56

要扩展上述内容,您需要获取历史对象.如果您正在使用BrowserRouter,则可以使用高阶组件(HoC)导入withRouter和包装组件,以便通过props访问历史对象的属性和函数.

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);
Run Code Online (Sandbox Code Playgroud)

唯一需要注意的是withRouter和大多数其他访问方式history似乎污染了道具,因为它们将对象解构为它.

  • 我认为[withRouter的当前版本](https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/withRouter.md)传递`history`而不是变量`listen`. (4认同)
  • 修改该职位以显示不听是很好;此代码中有内存泄漏。 (3认同)

Ser*_*kiy 30

你应该使用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}`)
})
Run Code Online (Sandbox Code Playgroud)

  • 潜在的内存泄漏!您一定要这样做!“当您使用history.listen附加侦听器时,它将返回一个可用于删除该侦听器的函数,然后可以在清除逻辑中调用该函数:const unlisten = history.listen(myListener); unlisten(); (9认同)
  • history.pushState() 和 history.replaceState() 调用不会触发 popstate 事件,因此仅此一项不会涵盖所有路由更改。 (2认同)

小智 19

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]);

}
Run Code Online (Sandbox Code Playgroud)

带钩子


Ale*_*lex 10

withRouterhistory.listenuseEffect(React Hooks)配合得很好:

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

    //...
}

export default withRouter(Component)
Run Code Online (Sandbox Code Playgroud)

每当更改路线时,都会触发监听器回调,并且的返回值history.listen是与配合使用的关闭处理程序useEffect


wei*_* ou 8

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

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

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

  return null;
}
Run Code Online (Sandbox Code Playgroud)


Tym*_*mek 7

带挂钩:

import { useEffect } from 'react'
import { withRouter } from 'react-router-dom'
import { history as historyShape } from 'react-router-prop-types'

const DebugHistory = ({ history }) => {
  useEffect(() => {
    console.log('> Router', history.action, history.location])
  }, [history.location.key])

  return null
}

DebugHistory.propTypes = { history: historyShape }

export default withRouter(DebugHistory)
Run Code Online (Sandbox Code Playgroud)

导入并渲染为<DebugHistory>组件


Ala*_*lan 6

对于反应钩子,我正在使用useEffect

import React from 'react'
const history = useHistory()
const queryString = require('query-string')
const parsed = queryString.parse(location.search)
const [search, setSearch] = useState(parsed.search ? parsed.search : '')

useEffect(() => {
  const parsedSearch = parsed.search ? parsed.search : ''
  if (parsedSearch !== search) {
    // do some action! The route Changed!
  }
}, [location.search])
Run Code Online (Sandbox Code Playgroud)

在此示例中,当路线更改时我向上滚动:

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

const ScrollToTop = () => {
  const location = useLocation()

  React.useEffect(() => {
    window.scrollTo(0, 0)
  }, [location.key])

  return null
}

export default ScrollToTop
Run Code Online (Sandbox Code Playgroud)