Thank you for opening this page in advance. I am a self-taught coder. And now I am making my personal page with Bootstrap.
What I want to do now is; SPA feature of React.js. All I understand this feature is;
- install "react-router-dom",
- import { Link, NavLink } from "react-router-dom";
- And replace those anchor and href tag to Link to=
The following code is in 'src' folder.
Navbar.js
import React from "react";
import logoImage from "../ponents/logo.png";
// React fontawesome imports
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faBars } from "@fortawesome/free-solid-svg-icons";
import { Link, NavLink } from "react-router-dom";
const Navbar = () => {
return (
<nav className="navbar navbar-expand-lg navbar-light bg-white">
<div className="container-fluid">
<a className="navbar-brand mr-auto" href="#"><img className="logo" src={logoImage} alt="logoImage"/></a
<button
className="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<FontAwesomeIcon icon={faBars} style={{ color: "#2ff1f2" }}/>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<a className="nav-link active" aria-current="page" href="../ponents/About">About me</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">Thoughts</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">Portfolio</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">Contacts</a>
</li>
</ul>
</div>
</div>
</nav>
)
}
export default Navbar;
App.js
import './App.css';
import "bootstrap/dist/css/bootstrap.min.css";
import Button from "react-bootstrap/Button";
import Particles from "react-particles-js";
import Navbar from "./ponents/Navbar";
import Header from "./ponents/Header";
import About from "./ponents/About";
function App() {
return (
<>
<Particles
className="particles-canvas"
params={{
particles: {
number: {
value: 30,
density: {
enable: true,
value_area: 900
}},
shape: {
type: "star",
stroke: {
width: 6,
color: "#f9ab00"
}}}}}
/>
<Navbar />
<Header />
<About />
</>
);
}
export default App;
Header.js
import React from "react";
import Typed from "react-typed";
import { Link } from "react-router-dom";
const Header = () => {
return (
<div className="header-wraper">
<div className="main-info">
<h1>Wele, this is my own personal page</h1>
<Typed
className="typed-text"
strings={["text message to display in the centre of the page"]}
typeSpeed={80}
/>
<a href="#" className="btn-main-offer">Details</a>
</div>
</div>
)
}
export default Header;
And soon as I replace
<a className="nav-link" href="#">Thoughts</a>
to
<Link to="../ponents/About">Thoughts</Link>
It stops working with this following error message.
×
Error: Invariant failed: You should not use <Link> outside a <Router>
invariant
C:/Users/Administrator/my-portfolio/node_modules/tiny-invariant/dist/tiny-invariant.esm.js:10
(anonymous function)
C:/Users/Administrator/modules/Link.js:88
85 | return (
86 | <RouterContext.Consumer>
87 | {context => {
> 88 | invariant(context, "You should not use <Link> outside a <Router>");
| ^ 89 |
90 | const { history } = context;
91 |
My understanding to this error is:
- I should make Router.js file in src folder.
- I should just start again without Bootstrap first. Once SPA feature is done, then I can start work on this CSS feature as CSS in JS (e.g. const something = div.styled ``;)
I know this sounds ridiculous, but this is the best option I could think for now.
Question is, Where should I begin investigating this error message?
I am currently relying on this document page to remove the error message. 1st Example: Basic Routing -
I would appreciate your opinion. Thank you. If I found a solution, I will update it with mine here.
Thank you for opening this page in advance. I am a self-taught coder. And now I am making my personal page with Bootstrap.
What I want to do now is; SPA feature of React.js. All I understand this feature is;
- install "react-router-dom",
- import { Link, NavLink } from "react-router-dom";
- And replace those anchor and href tag to Link to=
The following code is in 'src' folder.
Navbar.js
import React from "react";
import logoImage from "../ponents/logo.png";
// React fontawesome imports
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faBars } from "@fortawesome/free-solid-svg-icons";
import { Link, NavLink } from "react-router-dom";
const Navbar = () => {
return (
<nav className="navbar navbar-expand-lg navbar-light bg-white">
<div className="container-fluid">
<a className="navbar-brand mr-auto" href="#"><img className="logo" src={logoImage} alt="logoImage"/></a
<button
className="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<FontAwesomeIcon icon={faBars} style={{ color: "#2ff1f2" }}/>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<a className="nav-link active" aria-current="page" href="../ponents/About">About me</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">Thoughts</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">Portfolio</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">Contacts</a>
</li>
</ul>
</div>
</div>
</nav>
)
}
export default Navbar;
App.js
import './App.css';
import "bootstrap/dist/css/bootstrap.min.css";
import Button from "react-bootstrap/Button";
import Particles from "react-particles-js";
import Navbar from "./ponents/Navbar";
import Header from "./ponents/Header";
import About from "./ponents/About";
function App() {
return (
<>
<Particles
className="particles-canvas"
params={{
particles: {
number: {
value: 30,
density: {
enable: true,
value_area: 900
}},
shape: {
type: "star",
stroke: {
width: 6,
color: "#f9ab00"
}}}}}
/>
<Navbar />
<Header />
<About />
</>
);
}
export default App;
Header.js
import React from "react";
import Typed from "react-typed";
import { Link } from "react-router-dom";
const Header = () => {
return (
<div className="header-wraper">
<div className="main-info">
<h1>Wele, this is my own personal page</h1>
<Typed
className="typed-text"
strings={["text message to display in the centre of the page"]}
typeSpeed={80}
/>
<a href="#" className="btn-main-offer">Details</a>
</div>
</div>
)
}
export default Header;
And soon as I replace
<a className="nav-link" href="#">Thoughts</a>
to
<Link to="../ponents/About">Thoughts</Link>
It stops working with this following error message.
×
Error: Invariant failed: You should not use <Link> outside a <Router>
invariant
C:/Users/Administrator/my-portfolio/node_modules/tiny-invariant/dist/tiny-invariant.esm.js:10
(anonymous function)
C:/Users/Administrator/modules/Link.js:88
85 | return (
86 | <RouterContext.Consumer>
87 | {context => {
> 88 | invariant(context, "You should not use <Link> outside a <Router>");
| ^ 89 |
90 | const { history } = context;
91 |
My understanding to this error is:
- I should make Router.js file in src folder.
- I should just start again without Bootstrap first. Once SPA feature is done, then I can start work on this CSS feature as CSS in JS (e.g. const something = div.styled ``;)
I know this sounds ridiculous, but this is the best option I could think for now.
Question is, Where should I begin investigating this error message?
I am currently relying on this document page to remove the error message. 1st Example: Basic Routing - https://reactrouter./web/guides/quick-start
I would appreciate your opinion. Thank you. If I found a solution, I will update it with mine here.
Share Improve this question asked Apr 10, 2021 at 15:00 mireumireumireumireu 1,0251 gold badge8 silver badges11 bronze badges 1- Thank you for answering the question! Now I understand that the error message means a tag to include its required one. I better be sure to include both imported one and the thing after claiming return of its function. – mireumireu Commented Apr 11, 2021 at 11:24
3 Answers
Reset to default 3This is a good question, but, in order to answer it the best way, you will need to work with several files, as I'm sure you're already aware of.
To start, assuming you used create-react-app
, go to the index.js file, and wrap everything from the first parameter with react-router-dom
's BrowserRouter
ponent. It should look like the following:
index.js
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<BrowserRouter>
<React.StrictMode>
<App />
</React.StrictMode>
</BrowserRouter>,
document.getElementById("root")
);
Next, you will want to use react-router-dom
's Switch ponent to wrap all the application's routes.
App.js
import { Route, Switch } from "react-router";
import Navbar from "./ponents/Navbar";
import Header from "./ponents/Header";
import About from "./ponents/About";
// Particles ponent removed for explanation
function App() {
return (
<Navbar />
<Header />
// When a link is clicked, the ponent will appear within the following div,
// so if you want certain elements to stay where they are on the page, wrap
// and place the Switch ponent accordingly.
<div className='pages'>
<Switch>
<Route path='/about' ponent={About} />
<Route path='/profile' ponent={profile} />
<Route path='/thoughts' ponent={Thoughts} />
<Route path='/contacts' ponent={Contacts} />
</Switch>
</div>
);
}
export default App;
Now, within any child ponent of App
, you can use react-router-dom
Links
(I personally prefer using NavLink
due to its ease of styling). This could be done by the following:
Navbar.js
import { NavLink } from "react-router-dom";
const Navbar = (props) => {
return (
<nav className="navbar navbar-expand-lg navbar-light bg-white">
<div className="container-fluid">
<NavLink className="navbar-brand mr-auto" to='/home'>
<img className="logo" src={logoImage} alt="logoImage"/>
</NavLink
<button
className="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<FontAwesomeIcon icon={faBars} style={{ color: "#2ff1f2" }}/>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<NavLink className="nav-link active" to='/about'>About me</NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to='/thoughts'>Thoughts</NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to='/portfolio'>Portfolio</NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to='/contacts'>Contacts</NavLink>
</li>
</ul>
</div>
</div>
</nav>
)
};
export default Navbar;
After doing what is shown below, you will be able to navigate throughout your page using react-router-dom
.
Router
is a ponent provided by react-router-dom
As the error says, Link can be used inside Router
.
Also, path for Link should actual browser url and not the path of the ponent. Ideal way is to add routes for each ponent.
For Example your App can be like this: (Only for reference)
function App() {
return (
<Router>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/">
<Navbar />
</Route>
</Switch>
</Router>
);
}
Yes, you can do that, this error happen since you are missing to wrap <Link>
ponent via <Router>
...
If you like to put it for all project, you can simply do this:
<Router>
<App />
</Router>
Example:
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/users">Users</Link>
</li>
</ul>
</nav>
{/* A <Switch> looks through its children <Route>s and
renders the first one that matches the current URL. */}
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</div>
</Router>