client-side routing: navigating between views without leaving the React app
options:
hash-based client-side routing, e.g.:
example.com/#/homeexample.com/#/shop/cartclient-side routing based on on the history API, e.g.:
example.com/homeexample.com/shop/cartfor the second method, the server needs additional configuration
npm package: react-router-dom
the entire application is enclosed in a BrowserRouter element:
// index.tsx
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
rootElement
);
<Route> - a component that renders its content when active<Routes> - a container for <Route> elements<Link> / <NavLink> - are used in place of <a> elementsfunction App() {
return (
<div>
<NavLink to="/">home</NavLink>{' '}
<NavLink to="/about">about</NavLink>
<Routes>
<Route path="/" element={<HomeView />} />
<Route path="/about" element={<AboutView />} />
<Route path="*" element={<NotFoundView />} />
</Routes>
</div>
);
}
function App() {
return (
<Routes>
<Route path="/" element={<HomeView />} />
<Route path="/about" element={<AboutView />} />
<Route path="/shop" element={<ShopView />}>
<Route index={true} element={<ShopIndex />} />
<Route path="/products" element={<Products />} />
<Route path="/cart" element={<Cart />} />
</Route>
</Routes>
);
}
the output of a sub-route is displayed in the <Outlet> of the parent route's element:
function ShopView() {
return (
<div>
<h1>Shop</h1>
<NavLink to="/shop">shop index</NavLink>
<NavLink to="/shop/products">products</NavLink>
<NavLink to="/shop/cart">cart</NavLink>
<Outlet />
</div>
);
}
<Route
path="/products/:productId"
element={<ProductDetails />}
/>
function ProductDetails() {
const { productId } = useParams();
// ...
}
const navigate = useNavigate();
// ...
navigate('/');
styling active links differently:
<NavLink
to="/about"
className={(arg) =>
arg.isActive ? 'NavLink NavLink--Active' : 'NavLink'
}
>
...
</NavLink>
creating a reusable component:
function MyNavLink(
props: ComponentPropsWithoutRef<typeof NavLink>
) {
return (
<NavLink
{...props}
className={(arg) =>
arg.isActive ? 'NavLink NavLink--Active' : 'NavLink'
}
/>
);
}
create routes in the todo app, e.g.:
//about/add/stats