At present, React Router is the most popular routing solution for React applications. It is a complete routing package enriched with a long list of features.
However, there are many features in React Router that become irrelevant if you are building smaller applications. Let’s say you’re building an application that needs browser-based routing which leaves no room for features like memory routing and hash-based routing.
Thus, came into role the new Wouter.
The whole idea behind Wouter is that when a developer chooses to work with React Router, he utilizes only its 30 to 40% features. Wouter acts as a smaller alternative to React Router packed only with these handfuls of features that are commonly used.
Wouter is a minimalistic form of React Router and contains only the most commonly used functionalities.
In this blog, we will learn more about Wouter, its features, APIs, and much more-
Wouter is a tiny and minimalist-friendly router library for modern React and Preact apps that relies on Hooks.
Wouter provides simple and intuitive APIs that many developers and library authors appreciate. Some notable projects that use Wouter: Arcade, react-three-fiber, ssgl-doom-launcher, Ziro App and many more.
Whatever you could do with react-router you can achieve with Wouter too. Here are some features that makes Wouter preferable over React Router-
Along with these advantages, there are some downfalls as well, such as -
The very first step towards using Wouter is to install its package either from npm or yarn package manager, whichever you prefer -
npm install wouter
or
yarn add wouter
Now, to setup and implement Wouter, you will need to import <Link/> and <Route/> components. You can take help from this demo code -
import { Link, Route } from "wouter";
const App = () => (
<div>
<Link href="/users/Zedd">
<a className="link">Profile</a>
</Link>
<Route path="/inbox” component={InboxPage} />
<Route path="/about">About Us</Route>
<Route path="/users/:name">
{(params) => <div>Hello, {params.name}!</div>}
</Route>
</div>
);
export default App:
Wouter brings two types of APIs: React Hooks API and traditional component API. You can choose either one of them based upon your requirements.
While Hooks APIs might come in handy if you want to create custom routing components or building smaller applications, the component API will be preferred in case you’re building traditional application with navigation and pages.
Wouter uses react hooks which makes the custom interactions like route transition or accessing easier. It consists of 3 hooks that are easier to use and are explained below-
import { useRoute } from "wouter";
import { Transition } from "react-transition-group";
const AnimatedRoute = () => {
const [match, params] = useRoute("/users/:id");
return <Transition in={match}>Hi, this is: {params.id </Transition>;
};
import { useLocation } from "wouter";
const CurrentLocation = () => {
const [location, setLocation] = useLocation();
return (
<div>
{`The current page is: ${location}`}
<a onClick={() => setLocation("/somewhere")}>Click to update</a>
</div>
);
};
import { useRouter } from "wouter";
import useLocation from "wouter/use-location";
const Custom = () => {
const router = useRouter();
router.lastTransition = { path: "..." };
};
Now, let’s move to another type of Wouter API, i.e. component API-
The main Wouter components are described as given here -
The <Route /> component conditionally renders an app component when the current path matches with a specific pattern. The pattern is a string which might contain special characters that represent dynamic segments.
Here are given the ways in which a route’s body can be declared -
import { Route } from "wouter";
// simple form
<Route path="/home"><Home /></Route>
// render-prop style
<Route path="/users/:id">
{params => <UserPage id={params.id} />}
</Route>
// the `params` prop will be passed down to <Orders />
<Route path="/orders/:status" component={Orders} />
The <Link> component renders an anchor element <a> that enables us to navigate the route specified in the href prop. You can also customize it by adding your own <a> element or by linking it as a children element-
import { Link } from "wouter";
// All of these will produce the same html:
// <a href="/foo" class="active">Hello!</a>
<Link href="/foo" className="active">Hello!</Link>
<Link href="/foo"><a className="active">Hello!</a></Link>
<Link href="/foo"><A>Hello!</A></Link>
the <Switch> component is used in the cases of exclusive routing, where only one route is preferred and rendered at a time and all the other routes are ignored. It only renders the first matching route.
import { Route, Switch } from "wouter";
<Switch>
<Route path="/orders/all" component={AllOrders} />
<Route path="/orders/:status" component={Orders} />
</Switch>;
The <Redirect/> component, as the name implies, redirects the user to another path provided in the to prop. It makes use of useLocation hook to trigger the navigation internally inside the useEffect block.
import { Redirect } from "wouter";
const User = ({ userId }) => {
if (!userId) return <Redirect to="/login" />;
return <div> Current User is {userId} </div>;
};
Or, you can directly access the setLocation method for navigation by using useLocation hook.
import { useLocation } from "wouter";
const [location, setLocation] = useLocation();
fetchOrders().then((orders) => {
setOrders(orders);
setLocation("/app/orders");
});
Yes! Wouter provides support for server-side rendering. Isn’t it amazing?
Well, to use Wouter for SSR, you need to instruct the router that the current location must come from the HTTP request and not from the browser history.
For Wouter to handle these HTTP requests, you can replace the default useLocation hook by staticLocationHook.
import { renderToString } from "react-dom/server";
import { Router } from "wouter";
import staticLocationHook from "wouter/static-location";
import App from "./App";
const handleRequest = (req, res) => {
const prerendered = renderToString(
<Router hook={staticLocationHook(req.path)}>
<App />
</Router>
);
};
In application routing, having a default route is quite common and is used as a fallback in the cases where no other route matches. For instance, whenever there is 404 error, a default route is used to render the ‘404, Not Found’ error message.
The same thing is done in Wouter also. All you have to do is to combine a default route to a <Switch /> component, as shown below-
import { Switch, Route } from "wouter";
<Switch>
<Route path="/about">...</Route>
<Route>404, Not Found!</Route>
</Switch>;
If you favor small bundle-size and need to use routing in your app, you can use the useLocation hook which is only 341 bytes gzipped. Through this hook, you can reduce your app bundle size further.
import useLocation from "wouter/use-location";
const UsersRoute = () => {
const [location] = useLocation();
if (location !== "/users") return null;
// render the route
};
For more details, refer to this documentation link -
Although, Wouter is a wonderful routing solution in some cases, it cannot replace React Router. Also, you cannot switch your project to Wouter because it does not cover all the features of eact Router thus, this kind of migration will not work in most cases.
However, it is a great choice of routing solution for smaller projects where one needs some basic routing.
You might hit some claps, if you liked this blog 😉. Keep reading until the next time I come with a new blog.
Happy Reading!!