
Security News
pnpm 11.5 Adds Support for Recognizing npm Staged Publishes
pnpm 11.5 now recognizes npm staged publish approvals in release metadata, preventing those releases from being mistaken for lower-trust package publishes.
@flemminghansen/react-outlet-router
Advanced tools
Early release — API may change between minor versions.
React Outlet Router is a declarative client-side router, built with maintainability in mind.
View more complex example here
import {
RouterOutlet,
useInitRouter,
router,
} from "@flemminghansen/react-outlet-router";
import React from "react";
import ReactDOM from "react-dom/client";
function MockPage({ text }: {text: string}) {
return <div>{text}</div>
}
function App() {
const [isLoggedIn, setIsLoggedIn] = React.useState(false);
// Router will be reinitialized on login. This way we can create a guard for the loggedin route.
// For instance, the loggedin route and children won't be part of the routeTree until isLoggedIn is true.
useInitRouter(
{
defaultPageTitle: "My simple router",
default404Title: "404 - Page not found",
defaultNotFoundComponent: () => <div>404 - Page not found</div>,
fallback: <MockPage text="Please wait while we load your page dynamically..." />,
routeTree: {
"/": {
component: MainPage,
},
"/loggedin": {
removedIf: !isLoggedIn,
title: "Page one",
component: () => <MockPage text="Welcome!!" />,
children: {
// loggedin/user
"/user": {
title: "User page",
component: () => <MockPage text="You are awesome!" />,
},
},
},
},
},
[isLoggedIn]
);
const handleLogin = () => {
setIsLoggedIn(!isLoggedIn);
if (!isLoggedIn) {
router.replace('/loggedin')
}
}
return (
<>
<button onClick={handleLogin}>
{isLoggedIn ? "Log out" : "Log in"}
</button>
<RouterOutlet />
</>
);
}
const root = ReactDOM.createRoot(document.getElementById("app"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Installation is fairly simple using Node's package manager.
In your cli, run:
npm install @flemminghansen/react-outlet-router
useInitRouter takes one object with the following keys as defined by the interface IRemappedInitRouterProps.
interface IRemappedInitRouterProps {
prefix?: string;
defaultPageTitle: string;
default404Title?: string;
routeTree: Record<string, ILimitedRoute>; // key is the next part of the route, e.g. "/user"
fallback: React.ReactNode;
defaultNotFoundComponent: React.ComponentType<object>;
}
interface ILimitedRoute {
component: React.ComponentType<object>;
title?: string;
fallback?: React.ReactNode;
removedIf?: boolean;
pattern?: RegExp;
children?: Record<string, ILimitedRoute>;
}
Sets the document.title unless the routes specify something else
Defaults to: "404 - Page not found"
The component the router will render if there are no matches in the route tree.
The RouterOuter output is wrapped in a React Suspense Component. The fallback is shown while a dynamically loaded page is loaded.
Defaults to "/"
A part that will we prefixed to the pathname. This can be used if your domain hold multiple apps that lives under prefixes, such as:
Then you can prefix each app with "/myapp" or "mysecondapp", and each app will prefix every route with that prefix, thereby keeping the scope.
The routeTree is of type Record<string, ILimitedRoute>;, where the string is the path.
Each path must be prefixed with "/" e.g. "/user" or "/blog"
You can then use children to expand paths as in this example where the path to SettingsPage will be /user/settings.
"/user": {
title: "User Page",
component: UserPage,
children: {
"/settings": {
title: "Settings page",
component: SettingsPage,
},
},
},
It's also possible to add params as a wildcard. These params can use used with the router.getParams method to allow the component to handle further rendering.
But is can also be used to create custom 404 pages, or automatically redirect the user to a different path.
Currently redirect is done with the Redirect component, but this may be added as an option to the route in the future. See example:
"/user": {
title: "User Page",
component: UserPage,
children: {
"/settings": {
title: "User settings",
component: SettingsPage,
},
"/:invalid": {
component: () => <Redirect to="/user">, // This could also be a custom 404 page
},
},
},
Sets the component that will be rendered at the RouterOutput if route is match.
Pattern overrides the given path for the route. It is recommended to use with a param e.g. /:userid, so that the value can be read with the router.getParams method.
"/user": {
component: ParentPage,
children: {
"/:userid": {
// pattern will match integers like /1234
// but not strings like /123s
pattern: new RegExp(/^\d+$/),
component: UserPageForId,
},
},
},
In the above example, the userid must be an integer in order to match the pattern.
/user/1234 == match/user/1234s == nomatchThen in the UserPageForId component we use the router.getParams method to get the value.
import React from "react";
import { router } from "@flemminghansen/react-outlet-router";
export function UserPageForId() {
const { userid } = router.getParams();
// Do magics with the userid which you know is an integer.
...
}
children is an object from which you can expand the route as described under routeTree
Sets document.title for the given route
Sets a fallback for the given route. If no component is passed, it defaults to the fallback you've set for the router.
FAQs
Declarative client side router for React
We found that @flemminghansen/react-outlet-router demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
pnpm 11.5 now recognizes npm staged publish approvals in release metadata, preventing those releases from being mistaken for lower-trust package publishes.

Security News
Federal audit finds NIST lacked a plan to clear the NVD backlog, wasted funds on duplicate work, and delayed use of CISA data.

Research
/Security News
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.