client-side routing: navigating between views without leaving the React app
options:
hash-based client-side routing, e.g.:
example.com/#/home
example.com/#/shop/cart
client-side routing based on on the history API, e.g.:
example.com/home
example.com/shop/cart
for 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