[reactjs] You should not use <Link> outside a <Router>

I'm trying to set up react-router in an example application, and I'm getting the following error:

You should not use <Link> outside a <Router>

My app is set up like so:

Parent component

const router = (
  <div className="sans-serif">
    <Router histpry={browserHistory}>
      <Route path="/" component={Main}>
        <IndexRoute component={PhotoGrid}></IndexRoute>
        <Route path="/view/:postId" component={Single}></Route>
      </Route>
    </Router>
  </div>
);

render(<Main />, document.getElementById('root'));

Child/Main component

export default () => (
  <div>
    <h1>
      <Link to="/">Redux example</Link>
    </h1>
  </div>
)

Any idea what I'm doing wrong here?

Here's a Sandbox link to demonstrate the problem.

This question is related to reactjs react-router jsx

The answer is


For JEST users

if you use Jest for testing and this error happen just wrap your component with <BrowserRouter>

describe('Test suits for MyComponentWithLink', () => {
it('should match with snapshot', () => {
const tree = renderer
  .create(
    <BrowserRouter>
      <MyComponentWithLink/>
    </BrowserRouter>
  )
  .toJSON();
 expect(tree).toMatchSnapshot();
 });
});

I was getting this error because I was importing a reusable component from an npm library and the versions of react-router-dom did not match.

So make sure you use the same version in both places!


You can put the Link component inside the Router componet. Something like this:

 <Router>
        <Route path='/complete-profiles' component={Profiles} />
        <Link to='/complete-profiles'>
          <div>Completed Profiles</div>
        </Link>
      </Router>

I kinda come up with this code :

import React from 'react';
import { render } from 'react-dom';

// import componentns
import Main from './components/Main';
import PhotoGrid from './components/PhotoGrid';
import Single from './components/Single';

// import react router
import { Router, Route, IndexRoute, BrowserRouter, browserHistory} from 'react-router-dom'

class MainComponent extends React.Component {
  render() {
    return (
      <div>
        <BrowserRouter history={browserHistory}>
          <Route path="/" component={Main} >
            <IndexRoute component={PhotoGrid}></IndexRoute>
            <Route path="/view/:postId" component={Single}></Route>
          </Route>
        </BrowserRouter>
      </div>
    );
  }
}

render(<MainComponent />, document.getElementById('root'));

I think the error was because you were rendering the Main component, and the Main component didn't know anything about Router, so you have to render its father component.


Write router in place of Main in render (last line in the code). Like this ReactDOM.render(router, document.getElementById('root'));


If you don't want to change much, use below code inside onClick()method.

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

Make it simple:

render(<BrowserRouter><Main /></BrowserRouter>, document.getElementById('root'));

and don't forget: import { BrowserRouter } from "react-router-dom";


Whenever you try to show a Link on a page thats outside the BrowserRouter you will get that error.

This error message is essentially saying that any component that is not a child of our <Router> cannot contain any React Router related components.

You need to migrate your component hierarchy to how you see it in the first answer above. For anyone else reviewing this post who may need to look at more examples.

Let's say you have a Header.jscomponent that looks like this:

import React from 'react';
import { Link } from 'react-router-dom';

const Header = () => {
    return (
        <div className="ui secondary pointing menu">
            <Link to="/" className="item">
                Streamy
            </Link>
            <div className="right menu">
                <Link to="/" className="item">
                    All Streams
                </Link>
            </div>
        </div>
    );
};

export default Header;

And your App.js file looks like this:

import React from 'react';
import { BrowserRouter, Route, Link } from 'react-router-dom';
import StreamCreate from './streams/StreamCreate';
import StreamEdit from './streams/StreamEdit';
import StreamDelete from './streams/StreamDelete';
import StreamList from './streams/StreamList';
import StreamShow from './streams/StreamShow';
import Header from './Header';

const App = () => {
  return (
    <div className="ui container">
      <Header />
      <BrowserRouter>
        <div>
        <Route path="/" exact component={StreamList} />
        <Route path="/streams/new" exact component={StreamCreate} />
        <Route path="/streams/edit" exact component={StreamEdit} />
        <Route path="/streams/delete" exact component={StreamDelete} />
        <Route path="/streams/show" exact component={StreamShow} />
        </div> 
      </BrowserRouter>
    </div>
  );
};

export default App;

Notice that the Header.js component is making use of the Link tag from react-router-dom but the componet was placed outside the <BrowserRouter>, this will lead to the same error as the one experience by the OP. In this case, you can make the correction in one move:

import React from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
import StreamCreate from './streams/StreamCreate';
import StreamEdit from './streams/StreamEdit';
import StreamDelete from './streams/StreamDelete';
import StreamList from './streams/StreamList';
import StreamShow from './streams/StreamShow';
import Header from './Header';

const App = () => {
  return (
    <div className="ui container">
      <BrowserRouter>
        <div>
        <Header />
        <Route path="/" exact component={StreamList} />
        <Route path="/streams/new" exact component={StreamCreate} />
        <Route path="/streams/edit" exact component={StreamEdit} />
        <Route path="/streams/delete" exact component={StreamDelete} />
        <Route path="/streams/show" exact component={StreamShow} />
        </div> 
      </BrowserRouter>
    </div>
  );
};

export default App;

Please review carefully and ensure you have the <Header /> or whatever your component may be inside of not only the <BrowserRouter> but also inside of the <div>, otherwise you will also get the error that a Router may only have one child which is referring to the <div> which is the child of <BrowserRouter>. Everything else such as Route and components must go within it in the hierarchy.

So now the <Header /> is a child of the <BrowserRouter> within the <div> tags and it can successfully make use of the Link element.


Enclose Link component inside BrowserRouter component

 export default () => (
  <div>
   <h1>
      <BrowserRouter>
        <Link to="/">Redux example</Link>
      </BrowserRouter>
    </h1>
  </div>
)

Examples related to reactjs

Error: Node Sass version 5.0.0 is incompatible with ^4.0.0 TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined raised when starting react app Template not provided using create-react-app How to resolve the error on 'react-native start' Element implicitly has an 'any' type because expression of type 'string' can't be used to index Invalid hook call. Hooks can only be called inside of the body of a function component How to style components using makeStyles and still have lifecycle methods in Material UI? React Hook "useState" is called in function "app" which is neither a React function component or a custom React Hook function How to fix missing dependency warning when using useEffect React Hook? Unable to load script.Make sure you are either running a Metro server or that your bundle 'index.android.bundle' is packaged correctly for release

Examples related to react-router

React : difference between <Route exact path="/" /> and <Route path="/" /> You should not use <Link> outside a <Router> React Router Pass Param to Component Detect Route Change with react-router What is the best way to redirect a page using React Router? No restricted globals React-router v4 this.props.history.push(...) not working How to pass params with history.push/Link/Redirect in react-router v4? How to use Redirect in the new react-router-dom of Reactjs How to implement authenticated routes in React Router 4?

Examples related to jsx

TypeScript and React - children type? How to use componentWillMount() in React Hooks? expected assignment or function call: no-unused-expressions ReactJS You should not use <Link> outside a <Router> ReactJS - .JS vs .JSX React: Expected an assignment or function call and instead saw an expression React-Native Button style not work ReactJs: What should the PropTypes be for this.props.children? ReactJS map through Object Console logging for react?