Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/axtk/react-keenrouter
React router with componentless route matching
https://github.com/axtk/react-keenrouter
history-api react-hooks react-router router spa
Last synced: 2 months ago
JSON representation
React router with componentless route matching
- Host: GitHub
- URL: https://github.com/axtk/react-keenrouter
- Owner: axtk
- Created: 2021-02-06T23:30:28.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2024-05-21T05:08:13.000Z (8 months ago)
- Last Synced: 2024-05-21T06:25:45.930Z (8 months ago)
- Topics: history-api, react-hooks, react-router, router, spa
- Language: TypeScript
- Homepage: https://www.npmjs.com/package/react-keenrouter
- Size: 187 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
[![npm](https://img.shields.io/npm/v/react-keenrouter?labelColor=royalblue&color=royalblue&style=flat-square)](https://www.npmjs.com/package/react-keenrouter) [![GitHub](https://img.shields.io/badge/-GitHub-royalblue?labelColor=royalblue&color=royalblue&style=flat-square&logo=github)](https://github.com/axtk/react-keenrouter) ![React](https://img.shields.io/badge/%23-React-345?labelColor=345&color=345&style=flat-square) [![SSR](https://img.shields.io/badge/%23-SSR-345?labelColor=345&color=345&style=flat-square)](#server-side-rendering-ssr) ![TypeScript](https://img.shields.io/badge/%23-TypeScript-345?labelColor=345&color=345&style=flat-square)
# react-keenrouter
*React router with componentless route matching*
## Features
- componentless route matching
- doesn't enforce route collocation and tight coupling within a route hierarchy;
- works the same way both for components and dynamic route-based prop values;
- is akin to the common React pattern of [conditional rendering](https://react.dev/learn/conditional-rendering);
- the history-based route link components `` and `` with the props similar to those of the ordinary HTML link elements `` and `` (allowing for quick migration back and forth and working more like a polyfill to ordinary links);
- the `` component fit for both browser and server rendering;
- the utility converting plain HTML links (that can't be easily replaced with React components) to history-based links.## Example
```jsx
import {A, useRoute} from 'react-keenrouter';const appRoutes = {
HOME: '/',
INTRO: '/intro',
SECTION: /^\/section\/(?\d+)\/?$/,
};const allKnownRoutes = Object.values(appRoutes);
export const App = () => {
// the `useRoute()` hook subscribes the component to URL changes
let [route, withRoute] = useRoute();return (
{/* the route link component `A` looks similar to the
plain HTML link as it serves a similar purpose */}
Home
{' | '}
Intro
{withRoute(
appRoutes.HOME, (
Home
),
)}
{/* although `withRoute()` calls may appear in groups like
in this example, they work independently from each other
and may as well be used uncoupled in different places of
an application */}
{withRoute(
appRoutes.INTRO, (
Intro
),
)}
{/* the second and the third parameter of `withRoute()` can
be functions of `{href, params}`, with `params`
containing the capturing groups of the location pattern
if it is a regular expression */}
{withRoute(appRoutes.SECTION, ({params}) => (
Section #{params.id}
))}
{/* below, rendering `null` if the current location
matches `allKnownRoutes`, and the 404 error screen
otherwise */}
{withRoute(
allKnownRoutes,
null, (
404 Not found
),
)}
{
// `route` has a `window.location`-like API and can
// be handy for direct manipulation of the location
route.assign(appRoutes.HOME);
}}
>
Home
);
};
``````jsx
import {createRoot} from 'react-dom/client';
import {App} from './App';createRoot(document.querySelector('#app')).render();
```The `route` object returned from the `useRoute()` hook is an instance of the [`NavigationLocation`](https://www.npmjs.com/package/navloc) class provided by the wrapping `` component. If there is no `` up the React node tree (like with `` in the example above), a default `route` based on the current page location is used. A wrapping `` can be useful to provide a custom `route` prop value that accepts either a string location or a `NavigationLocation` class instance.
## Custom routing
The default `route` object returned from the `useRoute()` hook responds to changes in the entire URL, with `pathname`, `search`, and `hash` combined. This can be changed by providing an instance of a [customized](https://www.npmjs.com/package/navloc#custom-behavior) extension of the `NavigationLocation` class to the `Router` component.
```js
import {NavigationLocation} from 'react-keenrouter';export class PathLocation extends NavigationLocation {
deriveHref(location) {
// disregarding `search` and `hash`
return getPath(location, {search: false, hash: false});
}
}
``````jsx
import {createRoot} from 'react-dom/client';
import {Router} from 'react-keenrouter';
import {PathLocation} from './PathLocation';createRoot(document.querySelector('#app')).render(
,
);
```Extending the `NavigationLocation` class gives plenty of room for customization. This approach allows in fact to go beyond the URL-based routing altogether.
## Server-side rendering (SSR)
For the initial render on the server, the `` component can be used to pass the current route location to the application in essentially the same way as it can be done in the client-side code:
```jsx
// On the Express server
app.get('/', (req, res) => {
let html = ReactDOMServer.renderToString(
,
);// Sending the resulting HTML to the client.
});
```## Converting plain links
The `useRouteLinks()` hook can be helpful when it's necessary to convert plain HTML links to SPA route links if the route link component is not applicable right away (for instance, in a server-fetched static chunk of HTML content):
```js
useRouteLinks(containerRef, '.content a');
// `containerRef` is a value returned from the React's `useRef()` hook.
```