reactjs-使用react-rou检测路由更改

我必须根据浏览历史实现一些业务逻辑。

我想做的是这样的:

reactRouter.onUrlChange(url => {
   this.history.push(url);
});

URL更新后,有什么方法可以接收来自react-router的回调吗?

3个解决方案
70 votes

尝试检测路线更改时,可以使用history.listen((location, action) => { console.log(`The current URL is ${location.pathname}${location.search}${location.hash}`) console.log(`The last navigation action was ${action}`) }) 功能。 考虑到您正在使用history.listen((location, action) => { console.log(`The current URL is ${location.pathname}${location.search}${location.hash}`) console.log(`The last navigation action was ${action}`) }) ,请用unlisten HOC包装您的组件,以访问unregister道具。

history.listen((location, action) => { console.log(`The current URL is ${location.pathname}${location.search}${location.hash}`) console.log(`The last navigation action was ${action}`) }) 返回unlisten函数。 您可以通过收听将其用于unregister

您可以像这样配置路线

index.js

ReactDOM.render(
      <BrowserRouter>
            <AppContainer>
                   <Route exact path="/" Component={...} />
                   <Route exact path="/Home" Component={...} />
           </AppContainer>
        </BrowserRouter>,
  document.getElementById('root')
);

然后在AppContainer.js中

class App extends Component {

  componentWillMount() {
    this.unlisten = this.props.history.listen((location, action) => {
      console.log("on route change");
    });
  }
  componentWillUnmount() {
      this.unlisten();
  }
  render() {
     return (
         <div>{this.props.children}</div>
      );
  }
}
export default withRouter(App);

从历史记录文档中:

您可以使用收听当前位置的更改 history.listen((location, action) => { console.log(`The current URL is ${location.pathname}${location.search}${location.hash}`) console.log(`The last navigation action was ${action}`) })

history.listen((location, action) => {
      console.log(`The current URL is ${location.pathname}${location.search}${location.hash}`)
  console.log(`The last navigation action was ${action}`)
})

定位对象实现window.location的子集 界面,包括:

history.listen()

位置也可能具有以下属性:

location.state-此位置的某些其他状态不在URL中(history.listen()history

history.listen()-代表此位置的唯一字符串(受支持 在historybrowserHistory.listen()中)

操作是history.listen()之一,具体取决于用户 转到当前网址。

当您使用React-Router v3时,您可以使用如上所述的history软件包中的history.listen(),也可以使用browserHistory.listen()

您可以配置和使用您的路线,例如

import {browserHistory} from 'react-router';

class App extends React.Component {

    componentDidMount() {
          this.unlisten = browserHistory.listen( location =>  {
                console.log('route changes');

           });

    }
    componentWillUnmount() {
        this.unlisten();

    }
    render() {
        return (
               <Route path="/" onChange={yourHandler} component={AppContainer}>
                   <IndexRoute component={StaticContainer}  />
                   <Route path="/a" component={ContainerA}  />
                   <Route path="/b" component={ContainerB}  />
            </Route>
        )
    }
} 
Shubham Khatri answered 2020-06-23T18:16:34Z
11 votes

如果要全局监听import history from './history';对象,则必须自己创建它并将其传递给Router。然后可以使用其listen()方法来监听它:

// Use Router from react-router, not BrowserRouter.
import { Router } from 'react-router';

// Create history object.
import createHistory from 'history/createBrowserHistory';
const history = createHistory();

// Listen to history changes.
// You can unlisten by calling the constant (`unlisten()`).
const unlisten = history.listen((location, action) => {
  console.log(action, location.pathname, location.state);
});

// Pass history to Router.
<Router history={history}>
   ...
</Router>

如果将历史记录对象作为模块创建,则更好,因此您可以轻松地将其导入到可能需要的任何位置(例如import history from './history';

Fabian Schultz answered 2020-06-23T18:16:58Z
1 votes

我在React单页应用程序中导航到新屏幕后试图将ChromeVox屏幕阅读器聚焦到“屏幕”顶部时遇到了这个问题。 基本上,尝试通过跟随指向新的服务器呈现的网页的链接来模拟如果加载此页面时将发生的情况。

此解决方案不需要任何侦听器,它使用<nav><main>生命周期方法来触发单击,以在导航到新的URL路径时将ChromeVox聚焦在所需元素上。


实作

我创建了一个“屏幕”组件,该组件包裹在包含所有应用程序屏幕的react-router开关标签周围。

<Screen>
  <Switch>
    ... add <Route> for each screen here...
  </Switch>
</Screen>

<nav>组件

注意:此组件使用React + TypeScript

import React from 'react'
import { RouteComponentProps, withRouter } from 'react-router'

class Screen extends React.Component<RouteComponentProps> {
  public screen = React.createRef<HTMLDivElement>()
  public componentDidUpdate = (prevProps: RouteComponentProps) => {
    if (this.props.location.pathname !== prevProps.location.pathname) {
      // Hack: setTimeout delays click until end of current
      // event loop to ensure new screen has mounted.
      window.setTimeout(() => {
        this.screen.current!.click()
      }, 0)
    }
  }
  public render() {
    return <div ref={this.screen}>{this.props.children}</div>
  }
}

export default withRouter(Screen)

我曾尝试使用<nav>而不是<main>,但是单击导致ChromeVox停止读取当前正在读取的内容,并在我告诉它开始的地方重新开始。

高级说明:在此解决方案中,使用CSS order: -1;在Screen组件内部并在<main>内容之后呈现的导航<nav>视觉定位在main上方,方法是使用CSSorder: -1;19。因此,在伪代码中:

<Screen style={{ display: 'flex' }}>
  <main>
  <nav style={{ order: -1 }}>
<Screen>

如果您对此解决方案有任何想法,意见或建议,请添加评论。

Beau Smith answered 2020-06-23T18:17:54Z
translate from https://stackoverflow.com:/questions/45373742/detect-route-change-with-react-router