React router v6.7 does add /about to the end of the url but doesn't render the components. Normally putting the url does work though.
Navbar.js:
import React from 'react'
import PropTypes from 'prop-types'
import { Link, BrowserRouter } from 'react-router-dom'
export default function Navbar(props) {
return (
<BrowserRouter>
<nav className={`navbar navbar-expand-lg navbar-${props.mode} bg-${props.mode}`}>
<div className="container-fluid">
<Link className="navbar-brand" to="/">{props.title}</Link>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav me-auto mb-2 mb-lg-0">
<li className="nav-item">
<Link className="nav-link active" aria-current="page" to="/">Home</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/about">{props.aboutText}</Link>
</li>
<li className="nav-item dropdown">
<Link className="nav-link dropdown-toggle" to="/" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Dropdown
</Link>
<ul className="dropdown-menu" aria-labelledby="navbarDropdown">
<li><Link className="dropdown-item" to="/">Action</Link></li>
<li><Link className="dropdown-item" to="/">Another action</Link></li>
<li><hr className="dropdown-divider" /></li>
<li><Link className="dropdown-item" to="/">Something else here</Link></li>
</ul>
</li>
<li className="nav-item">
<Link to="/" className="nav-link disabled">Disabled</Link>
</li>
</ul>
<div className="form-check form-switch mx-3">
<input className="form-check-input" type="checkbox" role="switch" id="flexSwitchCheckDefault" onClick={props.toggleDarkMode} />
<label className="form-check-label" htmlFor="flexSwitchCheckDefault">Dark Mode</label>
</div>
<form className="d-flex">
<input className="form-control me-2" type="search" placeholder="Search" aria-label="Search" />
<button className="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
</BrowserRouter>
)
}
Navbar.propTypes = {
title: PropTypes.string.isRequired,
aboutText: PropTypes.string
}
Navbar.defaultProps = {
title: "Enter your Title",
aboutText: "About"
}
App.js
// import logo from './logo.svg';
import { useState } from 'react';
import './App.css';
import About from './components/About';
import Navbar from './components/Navbar';
import TextForm from './components/TextForm';
import {
createBrowserRouter,
RouterProvider,
} from "react-router-dom";
const router = createBrowserRouter([
{
path: "/",
element: <TextForm />,
},
{
path: "/about",
element: <About />
}
]);
function App() {
const [mode, setMode] = useState("light");
const toggleDarkMode = (event) => {
if (event.target.checked) {
setMode("dark");
document.body.style.backgroundColor = "#15181a";
document.body.style.color = "white";
}
else {
setMode("light");
document.body.style.backgroundColor = "white";
document.body.style.color = "black";
}
}
return (
<>
<Navbar title="TextUtils" aboutText="About Us" mode={mode} toggleDarkMode={toggleDarkMode} />
<RouterProvider router={router} />
</>
);
}
export default App;
Expectation: Link to should render the component into the DOM without reloading.
Reality: The url gets concatenated but the page actually doesn't render anything.
<BrowserRouter>
inside NavBar
which I don't believe is needed. Does the problem get fixed if you simply remove that? (I wish I had more experience with React Router - I've used it in one previous project but I'm not familiar at all with the newer v6 API, and the docs don't seem to be the clearest! This page though suggests that you don't need a BrowserRouter
when you're already using createBrowserRouter
.) Your <RouterProvider />
needs to wrap the NavBar
component with router
prop. Check out the official documentation.
What you're currently doing is wrapping the Navbar
but you have provided no router
instance. So it doesn't know the routes and which component to render when routes change.
Refactor App.js like this:
<>
<RouterProvider router={router}>
<Navbar title="TextUtils" aboutText="About Us" mode={mode} toggleDarkMode={toggleDarkMode} />
</RouterProvider>
</>
And remove RouterProvider
parent component from Navbar