2

I am working on a React app that is 'remote controlled' and am trying to connect the app's tab navigation via Pusher. I am using react-router-dom and have set up my connection to Pusher and the channels it listens to in the componentDidMount. I need to have the app change URL navigation each time a message is returned but cannot figure out what the correct way to 'push' it is. I have google many threads about programmatically navigating react-router-dom and have tried this.history.push(), this.props.history.push() and it's always throwing an error that history is undefined. The listeners reside in the same Component as the routing itself.

    import React, { Component } from 'react';
    import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
    import axios from 'axios';
    import Pusher from 'pusher-js';

    import Component1 from './Component1';
    import Component2 from './Component2';

    export default class AppRouter extends Component{

    componentDidMount() {
          const pusher = new Pusher('8675309', { cluster: 'us2', encrypted: true });
          const nav_channel = pusher.subscribe('nav');
          nav_channel.bind('message', data => { this.props.history.push(data.message) });
    }

...

render(){
    return(
      <Router>
        <Switch>
          <Route path='/path1' render={() => <Component1 navigate={this.handleNavChange} />} />
          <Route path="/path2" render={() => <Component2 navigate={this.handleNavChange} />} />

        </Switch>
      </Router>
    )
  }

    }

I need the app to change the URL or the routing each time the message is received from another connected app but I cannot figure out how to make react-router-dom (v4) do it within the same component as the Router itself. Any information or pointing me to a resource would be highly appreciated.

Wally Kolcz
  • 1,604
  • 3
  • 24
  • 45

2 Answers2

4

You need to use the withRouter decorator from React-Router to get access to match, location, and history.

import { withRouter } from 'react-router'

Wrap your component when exporting

export default withRouter(yourComponent)

Then you will have access to history from props.

https://reacttraining.com/react-router/core/api/withRouter

andrewgi
  • 620
  • 1
  • 7
  • 22
  • Thank you! So I cannot do it within the same component that had the Router itself? I am getting an 'You should not use or withRouter() outside a ' when I try to export my component with withRouter(AppRouter) – Wally Kolcz May 30 '18 at 14:32
  • Happy to help. That's correct. it's only for use within Component 1 or Component 2 as shown in your example. – andrewgi May 30 '18 at 15:14
2

To add on to andrewgi's answer:

After using withRouter() on your component, OR a parent component, try the following code in your component:

static contextTypes = {
    router: PropTypes.object,
    location: PropTypes.object
}

These should be defined, you can try console.log(this.context.router, this.context.location)

Then, to navigate programmatically, call

this.context.router.history.push('/someRoute');

Note: the context API is not stable. See Programmatically navigate using react router and https://reactjs.org/docs/context.html#why-not-to-use-context.

Julian H
  • 91
  • 1
  • 8