Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I programaticly navigate to a route from an event handler in React Router 4.0?

I need to navigate to a route after an event is successful. This seems to have changed since previous versions. Previously we would do this:

import { browserHistory } from 'react-router';
...
handleClick(){
  doSomething();
  browserHistory.push('/some/path');
}
like image 550
Jared Martin Avatar asked Mar 24 '17 05:03

Jared Martin


People also ask

How do you navigate to a specific route programmatically in react?

The primary way you programmatically navigate using React Router v4+ is by using a <Redirect /> component, and it's a recommended method that helps the user navigate between routes. Using the Redirect component is a different approach but just as valid.

How do you programmatically navigate using react router v4?

There are two ways to programmatically navigate with React Router - <Navigate /> and navigate() . You can get access to Navigate by importing it from the react-router-dom package and you can get access to navigate by using the custom useNavigate Hook.

Is it possible to configure routes programmatically in react?

Since v4 of React Router, there are three approaches that you can take to programmatic routing within components. Use the withRouter higher-order component. Use the context .


1 Answers

This example works in react-router and react-router-dom v4.0.0.

We have 3 components:

  • App.js - holds both Component 1 and Component 2
  • Component1.js - not wrapped in a Route and will always be rendered, but this will not have a reference of the "route props" - (history, location, match...)
  • Component2.js - rendered only if the route location match. Important thing to note that this component will be rendered with "route props"

To navigate programmatically, you can use react-router history object.

this.props.history.push('path');

This will work right off the bat for components rendered via Route, as these components will already have access to the route props (history). In our example this is Component2. However, for components that are not rendered via a Route (e.g. Component1), you would need to wrap it in withRouter to give you access to the history object.


App.js

import React, { Component } from 'react';
import { BrowserRouter, Route } from 'react-router-dom';

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

class App extends Component {
  render() {
    return (
      <BrowserRouter>
        <div>
          <Component1 />
          <Route path="/render1" render={() => <div>Rendered from Component1</div>} />
          <Route path="/" component={Component2} />
          <Route path="/render2" render={() => <div>Rendered from Component2</div>} />
        </div>
      </BrowserRouter>
    )
  }
}

export default App;

Component1.js

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

class Component1 extends React.Component {

  handleButtonClick() {
    this.props.history.push('/render1');
  }

  render() {
    return (
      <div>
        <h1>Component 1</h1>
        <button onClick={this.handleButtonClick.bind(this)}>Component 1 Button</button>
      </div>
    );
  }
}

const Component1WithRouter = withRouter(Component1);
export default Component1WithRouter;

For Component1, we wrapped it in withRouter, and then exported the returned wrapped object. Some gotcha, notice that in App.js, we still reference it as Component1 instead of Component1WithRouter


Component2.js

import React from 'react';

class Component2 extends React.Component {

  handleButtonClick() {
    this.props.history.push('/render2');
  }

  render() {
    return (
      <div>
        <h1>Component 2</h1>
        <button onClick={this.handleButtonClick.bind(this)}>Component 2 Button</button>
      </div>
    );
  }
}

export default Component2;

For Component2, the history object is already available from this.props. You just need to invoke the push function.

like image 50
cchaos Avatar answered Nov 10 '22 00:11

cchaos