score:71
I'm assuming that you are using React-Router V4, as you used the same in the original Sandbox Link.
You are rendering the Main
component in the call to ReactDOM.render
that renders a Link
and Main component is outside of Router
, that's why it is throwing the error:
You should not use <Link> outside a <Router>
Changes:
Use any one of these Routers, BrowserRouter/HashRouter etc..., because you are using React-Router V4.
Router can have only one child, so wrap all the routes in a
div
or Switch.React-Router V4, doesn't have the concept of nested routes, if you wants to use nested routes then define those routes directly inside that component.
Check this working example with each of these changes.
Parent Component:
const App = () => (
<BrowserRouter>
<div className="sans-serif">
<Route path="/" component={Main} />
<Route path="/view/:postId" component={Single} />
</div>
</BrowserRouter>
);
render(<App />, document.getElementById('root'));
Main
component from route
import React from 'react';
import { Link } from 'react-router-dom';
export default () => (
<div>
<h1>
<Link to="/">Redux example</Link>
</h1>
</div>
)
Etc.
Also check this answer: Nested routes with react router v4
score:-13
If you don't want to change much, use below code inside onClick()method.
this.props.history.push('/');
score:0
Write router in place of Main in render (last line in the code). Like this ReactDOM.render(router, document.getElementById('root'));
score:0
I base my answer on this article. Here's a simple solution.
// index.test.tsx
import React from "react";
import { render, screen } from "@testing-library/react";
import { Router } from "react-router-dom";
import { createBrowserHistory } from "history";
import Login from ".";
it("should display Login", () => {
const history = createBrowserHistory();
render(
<Router history={history}>
<Login />
</Router>
);
const linkElement = screen.getByText(/Login/i);
expect(linkElement).toBeInTheDocument();
});
score:0
Here is my solution, I use react testing library that comes with create-react-app. I know is simpler solution to what you asked, but I was missing the imports in the other answers so I just put it altogether. Here is the test file:
// HomePage.test.js
import { render, screen } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import HomePage from './HomePage';
it('Homepage contains heading 1', () => {
render(
<BrowserRouter>
<HomePage />
</BrowserRouter>
);
screen.getByRole('heading', { level: 1 });
});
it('Homepage contains link', () => {
render(
<BrowserRouter>
<HomePage />
</BrowserRouter>
);
expect(screen.getByRole('link')).toHaveAttribute('href', '/articles');
});
The main component that I would be testing would look like this
// HomePage.js
import React from 'react';
import { Link } from 'react-router-dom';
const HomePage = () => {
return (
<>
<h1>Welcome to React page</h1>
<p>
Click on <Link to='/articles'>Articles</Link> to see what is shared
today
</p>
</>
);
};
export default HomePage;
score:1
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>
score:1
Why not try to create another component that just uses the BrowserRouter from "react-router-dom" and wrap your component with the Link inside it.
const ReduxExample () => (
<div>
<h1>
<Link to="/">Redux example</Link>
</h1>
</div>
)
then you can do this
const NewReduxExample = () => {
<BrowserRouter>
<ReduxExample />
</BrowserRouter>
};
score:1
Alternatively, you can do this in your index.js file in your src folder.
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import App from './App';
ReactDOM.render(<Router><App /></Router>, document.getElementById('root'));
Then in your Component.jsx file you can import Link
import { Link } from 'react-router-dom';
and use the Link like so without a Router/Route tag.
<Link to="/">Page</Link>
score:1
wrap every component inside BrowserRouter where you're calling reactDom.render like this
import {BrowserRouter} from 'react-router-dom'
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
score:2
add this to your index.js:
import { BrowserRouter as Router } from "react-router-dom";
and then wrap your <App />
within the <Router></Router>
to use links within your react application.
like this:
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router } from "react-router-dom";
import App from "./App";
ReactDOM.render(
<Router>
<App/>
</Router>,
document.getElementById('root'));
score:3
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.
score:4
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!
score:5
Make it simple:
render(<BrowserRouter><Main /></BrowserRouter>, document.getElementById('root'));
and don't forget: import { BrowserRouter } from "react-router-dom";
score:16
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.js
component 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.
score:21
Enclose Link component inside BrowserRouter component
export default () => (
<div>
<h1>
<BrowserRouter>
<Link to="/">Redux example</Link>
</BrowserRouter>
</h1>
</div>
)
score:139
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();
});
});
Source: stackoverflow.com
Related Query
- You should not use Link outside a Router using react-router-dom
- You should not use Route or withRouter() outside a Router when using react-router 4 and styled-component in react
- Adding a Link as a child of a Router with ReactDOM.render yields "You should not use <Link> outside a <Router>"
- Using React Router to load components You should not use <Link> outside a <Router>
- Using Link in Mapbox GL JS popup throws Error: Invariant failed: You should not use <Link> outside a <Router>
- You should not use Route outside a Router after use of withRouter
- React Router problem with "Link", Error: Invariant failed: You should not use <Link> outside a <Router>
- You should not use Route outside a router
- Invariant failed: You should not use <Switch> outside a <Router> using Static Router
- You should not use <Link> outside a <Router>
- Jest, Enzyme: Invariant Violation: You should not use <Route> or withRouter() outside a <Router>
- Invariant Violation: You should not use <Switch> outside a <Router>
- Invariant failed: You should not use <Route> outside a <Router>
- Storybook w/ react-router - You should not use <Link> outside <Router>
- connected-react-router - You should not use <Route> outside a <Router>
- React Testing Library Invariant failed: You should not use <Route> outside a <Router>
- React - Error: Invariant failed: You should not use <Link> outside a <Router>
- Uncaught Error: You should not use <Switch> outside a <Router>, but Switch is inside
- Jest snapshot testing error: You should not use <Link> outside a <Router>
- ReactJS Header Layout , You should not use <Link> outside a <Router>
- React Typescript Error: Invariant failed: You should not use <withRouter(App) /> outside a <Router>
- Invariant failed: You should not use <Link> outside a <Router>
- React. You should not use <withRouter(App) /> outside a <Router>
- Invariant failed: You should not use <Switch> outside a <Router>
- Storybook 5.2 (CSF) - How to add react-router-dom Link - "You should not use <Link> outside a <Router>"
- You should not use <Link> outside a <Router> error while creating tutorial app with react-admin
- Invariant failed: You should not use <withRouter(Sidebar) /> outside a <Router>
- Error: Invariant failed: You should not use <Route> outside a <Router>
- IE11, Adobe Analytics, React-Router with Error Message: "Invariant Violation: You should not use <Switch> outside a <Router>"
- When importing from a library, Invariant failed: You should not use <Route> outside a <Router>
More Query from same tag
- operator not return expected result
- Prepopulate semantic drop down with first value : React+ Typescript
- ReactJS: Usage of React.Fragment in Router
- How do I mock a custom property of the window object in Jest?
- Setting the state of a React Component from 2 input fields
- React Route v6 - useRoutes index = true property?
- Why jest doesn't call a function that is inside the useEffect hook?
- How do I create an API in React
- Anyway to serve /static from a prefixed URL (e.g. /client/static) with npm start?
- Attempted import error: 'Component' is not exported from './UserOutput/UserOutput'
- ReactJS this.state.feed.map is not a function
- Configuration for mobile-friendly Airbnb's react-dates library
- Firebase Phone Auth Recaptcha Verifier not being set to window/loading
- How to embed Twitter widget to Reactjs?
- Create clickable buttons on react-bootstrap-table on cell
- handling events in react
- How to add styles to part of a body text in react
- How to show dummy image in React when url is broken?
- Form fields shrinking too small on mobile
- React-Stars can't be combined with FontAwesome Icons in Firefox and IE
- How to window.addEventListener in React JS
- Redux Keep Session
- How to retain state of previous page while navigating back to it from another page?
- React app not working in Internet Explorer 11
- Z-index not adding item to the top
- display image from database in react in laravel
- React does not render recursive reactive components
- Get a $ in front of a variable within a .map() - React
- Background image with gradient overlay React
- Component rendering before ComponentDidMount and Axios sets the state