web-dev-qa-db-ja.com

反応ルータv4で経路の変更を監視するにはどうすればいいですか?

ルートとして機能するボタンがいくつかあります。経路が変更されるたびに、アクティブなボタンが変更されていることを確認したいです。

反応ルータv4で経路変更を監視する方法はありますか?

81
Kasper

私は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>
  }
}

それが役に立てば幸い

113
ledfusion

上記をさらに拡張するには、履歴オブジェクトにアクセスする必要があります。 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);

気を付けなければいけないことは、withRouterや他のほとんどのhistoryへのアクセス方法は、オブジェクトをそれに分解するときにプロップを汚染するように見えるということです。

49
Sam Parmenter

あなたは 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}`)
})
21
Sergey Reutskiy

フック付き:

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)

<DebugHistory>コンポーネントとしてインポートしてレンダリングする

2
Tymek

withRouterhistory.listen、およびuseEffect(React Hooks)は非常にうまく機能します。

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

    //...
}

export default withRouter(Component)

リスナーコールバックは、ルートが変更されるたびに起動し、history.listenの戻り値は、useEffectとうまく機能するシャットダウンハンドラーです。

2
Alex

場合によっては、次のようにrenderではなくcomponent属性を使用することがあります。

class App extends React.Component {

    constructor (props) {
        super(props);
    }

    onRouteChange (pageId) {
        console.log(pageId);
    }

    render () {
        return  <Switch>
                    <Route path="/" exact render={(props) => { 
                        this.onRouteChange('home');
                        return <HomePage {...props} />;
                    }} />
                    <Route path="/checkout" exact render={(props) => { 
                        this.onRouteChange('checkout');
                        return <CheckoutPage {...props} />;
                    }} />
                </Switch>
    }
}

onRouteChangeメソッドで状態を変更すると、「最大更新深度を超えました」というエラーが発生する可能性があることに注意してください。

0
Fernando