If I search "http://localhost:3000/" or "http://localhost:3000/login", my display is completely blank.
app.js
import React from 'react'
import Login from './pages/login'
import Home from './pages/home'
import Error from './pages/error'
import { Link, Router, Route, Routes } from 'react-router-dom';
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="*" element={<Error />} />
</Routes>
)
}
export default App;
home.js
import React from "react";
const Home = () => {
return <h1>The Home</h1>;
};
export default Home;
Refactor to look like:
import { Route, Routes, BrowserRouter } from 'react-router-dom';
// ...
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="*" element={<Error />} />
</Routes>
</BrowserRouter>
);
};
I work with react-router v6. I want to create a new route based on an id. On my homepage "example.com" I have a selection of articles. I want to create a detail view for each article "example.com/{id}". My approach looks like this:
App.tsx
import {
BrowserRouter,
Routes,
Route,
} from "react-router-dom";
import ProjectWrapper from "./components/ProjectWrapper";
import Home from "./pages/Home";
import PageError from "./pages/PageError";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} >
<Route path=":id" element={<ProjectWrapper />} />
</Route>
<Route path="*" element={<PageError />} />
</Routes>
</BrowserRouter>
);
}
ProjectWrapper.tsx
import { useParams } from "react-router-dom";
import { ProjectList } from "../pages/algorithms/ProjectList";
import PageError from "../pages/PageError";
function ProjectWrapper() {
const { id } = useParams();
const project = ProjectList.find((project) => project.id.toLowerCase() === id?.toLowerCase());
if (project === undefined) return (<PageError />);
return (
<div>
{project!.shortDescription}
</div>
)
}
export default ProjectWrapper;
Am I missing something ?
With the given routing code:
<Routes>
<Route path="/" element={<Home />} >
<Route path=":id" element={<ProjectWrapper />} />
</Route>
<Route path="*" element={<PageError />} />
</Routes>
Home is what is called a Layout Route. Layout routes render some common logic and UI, and an Outlet component for nested Routes to render their content when matched.
Example:
import { ..., Outlet } from 'react-router-dom';
const Home = () => {
...
return (
<>
...
<Outlet /> // <-- nested routes render content here
</>
);
};
If you don't want the Home component to render along with children routes then place it on its own route.
Examples:
<Routes>
<Route path="/" element={<Home />} />
<Route path="/:id" element={<ProjectWrapper />} />
<Route path="*" element={<PageError />} />
</Routes>
or
<Routes>
<Route path="/">
<Route index element={<Home />} />
<Route path=":id" element={<ProjectWrapper />} />
</Route>
<Route path="*" element={<PageError />} />
</Routes>
I'm trying to implement router in react-create-app but it always render "/" and showing Home or SignIn page. How can I solve this?
function AppRouter({ isLoggedIn, user }) {
return(
<Router>
<Routes>
<Route path="/profile" element={<Profile />} />
<Route path="/signUp" element={<SignUp />} />
{isLoggedIn
? <Route exact path={"/"} element={<Home user={user}/>} />
: <Route exact path={"/"} element={<SignIn />} />
}
</Routes>
</Router>
)
}
It seems you have a slight misunderstanding of how the HashRouter works with the UI.
import { HashRouter as Router, Route, Routes } from "react-router-dom";
import Profile from "./Profile";
import SignUp from "./SignUp";
import Home from "./Home";
export default function App() {
return (
<Router>
<Routes>
<Route path="/profile" element={<Profile />} />
<Route path="/signUp" element={<SignUp />} />
<Route path="/" element={<Home />} />
</Routes>
</Router>
);
}
The HashRouter handles routing with a URL hash value, i.e. everything after the "#" in the URL. If you are trying to render your app and access "<domain>/" instead of "<domain>/#/" the routing won't work.
For example in your running codesandbox demo, the base URL is "https://5p7hff.csb.app/". At this base URL the hash router isn't really working, and you should really be accessing "https://5p7hff.csb.app/#/" instead so the hash router is loaded and the app's internal routing can work.
From "https://5p7hff.csb.app/#/" you should be to then navigate to any of your routes, i.e. "https://5p7hff.csb.app/#/profile" and https://5p7hff.csb.app/#/signUp".
If you switch to a different router, like the BrowserRouter then the "/#/" is no longer used, the router and routes render from "/" where the app is running from. The routes would be "https://5p7hff.csb.app/", "https://5p7hff.csb.app/profile", and "https://5p7hff.csb.app/signUp".
So i have tried for quiet some time to hide the nav and footer components in certain pages of the site, but sadly no luck. I've tried multiple solutions on Stackoverflow, only one of them worked partially by creating a new Layout component and then putting that inside the Routes to then exclude the footer and nav from for example the login page. But the issue was that it worked, but on homepage it then only showed the footer and nav, and nothing in between like the design I made in the homepage.
The only solution that works for me is by creating the and like I did in the example, but then I cant exclude certain pages and hide them there...
This is how it looks currently and not working:
import React from "react";
import Home from ".//Pages/Home";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Dashboard from "./Pages/Dashboard";
import Login from "./Pages/Login";
import Price from "./Pages/Price";
import ErrorPage from "./Pages/ErrorPage";
import Navbar from "./components/Navbar";
import Footer from "./components/Footer";
import Profile from "./Pages/Profile";
function App() {
return (
<Router>
<nav>
<Navbar />
</nav>
<Routes>
<Route index element={<Home />} />
<Route path="/Dashboard" element={<Dashboard />} />
<Route path="/Login" element={<Login />} />
<Route path="/Price" element={<Price />} />
<Route path="/Profile/:username" element={<Profile />} />
<Route path="/*" element={<ErrorPage />} />
</Routes>
<footer>
<Footer />
</footer>
</Router>
);
}
export default App;
Hi you can do it by having a state that only when the state is true the nav and footer will render:
function App() {
const [showNav, setShowNav- = useState(true);
return (
<Router>
{ showNav &&
<nav>
<Navbar />
</nav>
}
<Routes>
<Route index element={<Home />} />
<Route path="/Dashboard" element={<Dashboard />} />
<Route path="/Login" element={<Login />} />
<Route path="/Price" element={<Price />} />
<Route path="/Profile/:username" element={<Profile />} />
<Route path="/*" element={<ErrorPage />} />
</Routes>
{showNav &&
<footer>
<Footer />
</footer>
</Router>
}
);
}
And for example, if you don't want to show the nav in the homepage you will pass the setShowNav function as a prop and will set it to false:
<Route index element={<Home funcNav={setShowNav}/>} />
in home page:
props.funcNav(false);
You can use modularization in your app segmenting it into different sections. This can best be accomplished by using nested routes in your app each. For example you could have example.com/routes/xxx have one layout and have example.com/other/xxx have another layout... You could also use this to optionally render the navbar and footer as you have mentioned.It is a good idea to segment your app if it has very different features/areas where different navbar/footer combinations need to be used. Here is an example using most of your code which would segment it into a main layout, and no layout.
App.js
import React from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import PageWithoutHeaderOrFooter from "./Pages/NoHeaderOrFooter";
import MainLayoutRoutes from "./Layouts/MainLayoutRoutes";
function App() {
return (
<Router>
<Routes>
<Route path="/noheaderorfooter" element={<PageWithoutHeaderOrFooter />} />
<Route path="*" element={<MainLayoutRoutes />} />
</Routes>
</Router>
);
}
export default App;
MainLayuotRoutes.js
import React from 'react';
import Home from ".//Pages/Home";
import Dashboard from "./Pages/Dashboard";
import Login from "./Pages/Login";
import Price from "./Pages/Price";
import ErrorPage from "./Pages/ErrorPage";
import Navbar from "./components/Navbar";
import Footer from "./components/Footer";
import Profile from "./Pages/Profile";
function MainLayoutRoutes() {
return (
<React.Fragment />
<nav>
<Navbar />
</nav>{/*This is outside the routes component on purpose read below*/}
<Routes>
<Route index element={<Home />} />
<Route path="/Dashboard" element={<Dashboard />} />
<Route path="/Login" element={<Login />} />
<Route path="/Price" element={<Price />} />
<Route path="/Profile/:username" element={<Profile />} />
<Route path="/*" element={<ErrorPage />} />
</Routes>
<footer>
<Footer />
</footer>
<React.Fragment />
)
}
export default MainLayoutRoutes;
A couple things I would like to note about this code.
First each child component in a Routes component must be a Route component (this doesn't include the element part of the Route component). This is why I am using a React.Fragment (you could have just as easily used <></>) if you didn't want an additional div rendered.
Secondly using this type of routing is good for segmenting your app into areas... Using areas not only is better for routing it is also better for SEO (where applicable as some crawlers don't yet support JavaScript).
Lastly I would like to mention if there is a rare case where there is only 1 page that you want a different navbar or footer, just use conditional rendering to take care of the edge case.
You can also use UseLocation from react-router-dom
const { pathname } = useLocation();
<footer>
{pathname !== '/<SOME_ROUTE>' &&
<Footer />}
</footer>
yes you should apply condition that will check if current location will display nav or not
You should use useLocation from react-router
To do this
Here is example from official documentation how you can do that.
Using Route components:
<Routes>
<Route path="/" element={<App />}>
<Route index element={<Home />} />
<Route path="teams" element={<Teams />}>
<Route path=":teamId" element={<Team />} />
<Route path=":teamId/edit" element={<EditTeam />} />
<Route path="new" element={<NewTeamForm />} />
<Route index element={<LeagueStandings />} />
</Route>
</Route>
<Route element={<PageLayout />}>
<Route path="/privacy" element={<Privacy />} />
<Route path="/tos" element={<Tos />} />
</Route>
<Route path="contact-us" element={<Contact />} />
</Routes>
Using useRoutes hook:
let routes = [
{
element: <App />,
path: "/",
children: [
{
index: true,
element: <Home />,
},
{
path: "teams",
element: <Teams />,
children: [
{
index: true,
element: <LeagueStandings />,
},
{
path: ":teamId",
element: <Team />,
},
{
path: ":teamId/edit",
element: <EditTeam />,
},
{
path: "new",
element: <NewTeamForm />,
},
],
},
],
},
{
element: <PageLayout />,
children: [
{
element: <Privacy />,
path: "/privacy",
},
{
element: <Tos />,
path: "/tos",
},
],
},
{
element: <Contact />,
path: "/contact-us",
},
];
And of course you should use <Outlet/> component inside <App /> and <PageLayout /> to render childrens inside those layouts.
App.js
<Router>
<Routes>
//your other route
<Route path="/404" element={<NotFound />} />
<Route path="*" element={<Navigate to="/404" />} />
</Routes>
</Router>
Navbar.js
const withouSidebarRoutes = ["404", "/signin", "/etc"];
const { pathname } = useLocation();
if (withouSidebarRoutes.some((item) => pathname.includes(item)))
return null;
Work fine for me :))
How can I config the basename, or keep a path in url like localhost:8000/app and when I have to redirect to another Route the Router identify this /app as part of url and do not change it, this is my component structure.
import React from 'react';
import { Router, Route, browserHistory, IndexRoute } from 'react-router';
<Router history={browserHistory} >
<Route component={App}>
<Route path="/" component={Home} />
<Route path="/login" component={LoginContainer} />
<Route path="apresentacao">
<IndexRoute component={NameContainer} />
<Route path="2" component={HsContainer} />
<Route path="3" component={McContainer} />
<Route path="4" component={MpvContainer} />
</Route>
</Route>
</Router>
If you are using React Router v4, you can use the basename prop of the Router component to change the base of your app.
import React from "react";
import { Router, Route, browserHistory, IndexRoute } from "react-router";
class App extends React.Component {
render() {
return (
<Router history={browserHistory} basename="/app">
<Route component={App}>
<Route path="/" component={Home} />
<Route path="/login" component={LoginContainer} />
<Route path="apresentacao">
<IndexRoute component={NameContainer} />
<Route path="2" component={HsContainer} />
<Route path="3" component={McContainer} />
<Route path="4" component={MpvContainer} />
</Route>
</Route>
</Router>
);
}
}
If you are using React Router v3, you need to install the history package separately and use the useBasename function.
import React from "react";
import { Router, Route, browserHistory, IndexRoute } from "react-router";
import { useBasename } from 'history'
class App extends React.Component {
render() {
return (
<Router history={useBasename(() => browserHistory)({ basename: '/app' })}>
<Route component={App}>
<Route path="/" component={Home} />
<Route path="/login" component={LoginContainer} />
<Route path="apresentacao">
<IndexRoute component={NameContainer} />
<Route path="2" component={HsContainer} />
<Route path="3" component={McContainer} />
<Route path="4" component={MpvContainer} />
</Route>
</Route>
</Router>
);
}
}