Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-router: How to manually invoke Link?

People also ask

How do I add a link to my router in React?

To add the link in the menu, use the <NavLink /> component by react-router-dom . The NavLink component provides a declarative way to navigate around the application. It is similar to the Link component, except it can apply an active style to the link if it is active.

How do I open external links in React router?

To add an external link with React Router, we can set the to prop to an object with the pathname property set to the external URL we go to when the link is clicked. to set the to prop to { pathname: "https://example.com" } to go to https://example.com when we click on the link.


React Router v5 - React 16.8+ with Hooks (updated 09/23/2020)

If you're leveraging React Hooks, you can take advantage of the useHistory API that comes from React Router v5.

import React, {useCallback} from 'react';
import {useHistory} from 'react-router-dom';

export default function StackOverflowExample() {
  const history = useHistory();
  const handleOnClick = useCallback(() => history.push('/sample'), [history]);

  return (
    <button type="button" onClick={handleOnClick}>
      Go home
    </button>
  );
}

Another way to write the click handler if you don't want to use useCallback

const handleOnClick = () => history.push('/sample');

React Router v4 - Redirect Component

The v4 recommended way is to allow your render method to catch a redirect. Use state or props to determine if the redirect component needs to be shown (which then trigger's a redirect).

import { Redirect } from 'react-router';

// ... your class implementation

handleOnClick = () => {
  // some action...
  // then redirect
  this.setState({redirect: true});
}

render() {
  if (this.state.redirect) {
    return <Redirect push to="/sample" />;
  }

  return <button onClick={this.handleOnClick} type="button">Button</button>;
}

Reference: https://reacttraining.com/react-router/web/api/Redirect

React Router v4 - Reference Router Context

You can also take advantage of Router's context that's exposed to the React component.

static contextTypes = {
  router: PropTypes.shape({
    history: PropTypes.shape({
      push: PropTypes.func.isRequired,
      replace: PropTypes.func.isRequired
    }).isRequired,
    staticContext: PropTypes.object
  }).isRequired
};

handleOnClick = () => {
  this.context.router.push('/sample');
}

This is how <Redirect /> works under the hood.

Reference: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Redirect.js#L46,L60

React Router v4 - Externally Mutate History Object

If you still need to do something similar to v2's implementation, you can create a copy of BrowserRouter then expose the history as an exportable constant. Below is a basic example but you can compose it to inject it with customizable props if needed. There are noted caveats with lifecycles, but it should always rerender the Router, just like in v2. This can be useful for redirects after an API request from an action function.

// browser router file...
import createHistory from 'history/createBrowserHistory';
import { Router } from 'react-router';

export const history = createHistory();

export default class BrowserRouter extends Component {
  render() {
    return <Router history={history} children={this.props.children} />
  }
}

// your main file...
import BrowserRouter from './relative/path/to/BrowserRouter';
import { render } from 'react-dom';

render(
  <BrowserRouter>
    <App/>
  </BrowserRouter>
);

// some file... where you don't have React instance references
import { history } from './relative/path/to/BrowserRouter';

history.push('/sample');

Latest BrowserRouter to extend: https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/BrowserRouter.js

React Router v2

Push a new state to the browserHistory instance:

import {browserHistory} from 'react-router';
// ...
browserHistory.push('/sample');

Reference: https://github.com/reactjs/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md


React Router 4 includes a withRouter HOC that gives you access to the history object via this.props:

import React, {Component} from 'react'
import {withRouter} from 'react-router-dom'

class Foo extends Component {
  constructor(props) {
    super(props)

    this.goHome = this.goHome.bind(this)
  }

  goHome() {
    this.props.history.push('/')
  }

  render() {
    <div className="foo">
      <button onClick={this.goHome} />
    </div>
  }
}

export default withRouter(Foo)

In the version 5.x, you can use useHistory hook of react-router-dom:

// Sample extracted from https://reacttraining.com/react-router/core/api/Hooks/usehistory
import { useHistory } from "react-router-dom";

function HomeButton() {
  const history = useHistory();

  function handleClick() {
    history.push("/home");
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}

https://github.com/rackt/react-router/blob/bf89168acb30b6dc9b0244360bcbac5081cf6b38/examples/transitions/app.js#L50

or you can even try executing onClick this (more violent solution):

window.location.assign("/sample");