One route - one physical page served from server
Changing the route leads to unload for the current page, and full load for the new page
When URL changed - we are staying on the same physical page but the content refreshed by JS
A single-page application (SPA) is a web application or website that interacts with the user by dynamically rewriting the current web page, instead of the default method of a web browser loading entire new pages. The goal is faster transitions that make the website feel more like a native app - wikipedia
npm i react-router-dom
<BrowserRouter></BrowserRouter>;
BrowserRouter might be configured for serving from sub root
<BrowserRouter>
<Routes>
</Routes>
</BrowserRouter>;
Routes container for a nested tree of elements that renders the branch that best matches the current location. React router supports multiple routes
<BrowserRouter>
<Routes>
<Route path="/" element={<IndexPage />} />
<Route path="/user" element={<UserPage />} />
</Routes>
</BrowserRouter>;
When user will open default page - the Index page will be shown, when he will open /user, the UserPage will be shown
<Link to="/user">Go to user page</Link>
const Forbidden = () => {
const navigate = useNavigate();
useEffect(() => {
navigate("/");
}, []);
return <>FORBIDDEN</>;
};
Use useNavigate hook for programmatic navigation
const Forbidden = () => <Navigate to="/" />
If this is not an option - use HashRouter, then your URL will be using hash to avoid querying backend http://localhost:3000/#/user/3
https://twitter.com/drag137
<Route path="/:userName" element={<UserPage />} />
const UserPage = () => {
const { userName } = useParams();
return <div>Hello user: {userName}</div>;
};
We also can use userName or other similar parameter to fetch the data from backend
Getting params inside the class-based component is not possible in react-router >=6
Imagine that you created a personal cabinet for the user. User have to login before visiting personal cabinet.
However, user might try to visit the cabinet without the authentication, using the direct link.
Thus, you need to guard it
type UserData = { user?: { authenticated: boolean } };
const UserPageGuard: FC<UserData> = ({ user }) =>
user && user.authenticated ?
<UserPage /> :
<Navigate to="/login" />;
<Routes>
<Route path="/login" element={"Please login"} />
<Route
path="/:userName"
element={<UserPageGuard user={userData} />}
/>
</Routes>
Now, if user is not authenticated, or no data is present, he will be automatically navigate to the login page
Imagine you created personal page for user: /user
Now you want to have two options of the view - default and posts but with the same layout
Then you might build your routing this way: default view withing /:user and posts view within /:user/posts
const UserPage = () => {
const { userName } = useParams();
return (
<>
Hello user: {userName}
<div>
View: <Outlet></Outlet>
</div>
</>
);
};
Outlet - the "portal" where your sub-route will be rendered
<div>
<Link to="">Default view</Link>
</div>
<div>
<Link to="posts">Posts view</Link>
</div>
<Route path="/:userName" element={<UserPage/>}>
<Route index element={"Default View"} />
<Route path="posts" element={"Showing all posts"} />
</Route>
Hello user: drag13 View: Default View
Hello user: drag13 View: Showing all posts
const AppApp = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="*" element={<NotFoundPage />} />
</Routes>
</BrowserRouter>
);
};
const AppApp = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/user/:id" element={'userpage'} />
<Route path="/user/" element={'userpage without id'} />
</Routes>
</BrowserRouter>
);
};
const LazyPage = lazy(() => import('./LazyPage'));
const AppApp = () => {
return (
<HashRouter>
<Routes>
<Route path="/" element={'DEFAULT'} />
<Route path="/lazy" element={<LazyPage />} />
</Routes>
</HashRouter>
);
};