Reputation: 995
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;
The following code is in 'src' folder.
Navbar.js
import React from "react";
import logoImage from "../components/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="../components/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 "./components/Navbar";
import Header from "./components/Header";
import About from "./components/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>Welcome, 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="../components/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 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.com/web/guides/quick-start
I would appreciate your opinion. Thank you. If I found a solution, I will update it with mine here.
Upvotes: 3
Views: 4748
Reputation: 215
This 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
component. 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 component to wrap all the application's routes.
App.js
import { Route, Switch } from "react-router";
import Navbar from "./components/Navbar";
import Header from "./components/Header";
import About from "./components/About";
// Particles component removed for explanation
function App() {
return (
<Navbar />
<Header />
// When a link is clicked, the component 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 component accordingly.
<div className='pages'>
<Switch>
<Route path='/about' component={About} />
<Route path='/profile' component={profile} />
<Route path='/thoughts' component={Thoughts} />
<Route path='/contacts' component={Contacts} />
</Switch>
</div>
);
}
export default App;
Now, within any child component 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
.
Upvotes: 3
Reputation: 3550
Yes, you can do that, this error happen since you are missing to wrap <Link>
component 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>
Upvotes: 1
Reputation: 12222
Router
is a component 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 component. Ideal way is to add routes for each component.
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>
);
}
Upvotes: 1