react-router9 v0.6.2
React Router9
Routing library for React. Renders components based on current url. Easy server-side rendering.
Why not React Router?
With React Router9, you can use History API, set properties of components (even dynamically), create dynamic routes using function as path, use ordinary <a></a>
links instead of Link
s (which React Router9 doesn't even have) and both lazy loading of routes and server-side rendering are simpler. React Router9 unifies *Component*
and Index*Component*
.
Also, React Router9 is significantly smaller than React Router. (React Router9 has around 14 kB, React Router has 52 kB; minified versions.)
Use
// npm
npm install --save react-router9
// Node.js, compiled to ES5 strict and minified.
import ReactRouter9 from "react-router9"; // const ReactRouter9 = require("react-router9");
// Node.js, neither compiled nor minified, requires support of async functions.
import ReactRouter9 from "react-router9/source.js"; // const ReactRouter9 = require("react-router9/source.js");
// In browser, compiled to ES5 strict and minified. Creates global variable.
<script src="https://cdn.rawgit.com/mik-jozef/react-router9/fe820700065fac9acbcb95525c0a3142907fa97c/index.js"></script>
// In browser, neither compiled nor minified, requires support of async functions.
<script src="https://cdn.rawgit.com/mik-jozef/react-router9/fe820700065fac9acbcb95525c0a3142907fa97c/source.js"></script>
Tutorial
When you use React Router9, your main component will be Router
with Route
s and Redirect
s as children.
const { Router, Route, Redirect } = ReactRouter9;
const router =
<Router> {/* Matching urls (you can use hashes, see API): */}
<Route path="about" /> {/* /about */}
<Route path="products"> {/* /products */}
<Route path="productA" /> {/* /products/productA */}
<Route path="productB" /> {/* /products/productB */}
<Route path=":productName" /> {/* /products/whatever */}
</Route>
<Redirect from="offers/::rest" to="products/::rest" />
</Router>
ReactDOM.render(router, document.getElementById("container"));
See matching algorithm below for more details about how routes are matched.
This example is a valid app, but except from redirecting "/offers/..." to "/products/...", it doesn't yet do anything. For it to render some components, we need to tell Route
s what components to render when they match.
const { Router, Route, Redirect } = ReactRouter9;
// Our components to render.
function Welcome(props) {
return <div>Hello!</div>;
}
function Products(props) {
return (
<div>
<h1>Products page</h1>
{props.children}
</div>
);
}
function A(props) {
return <div>Product A.</div>;
}
function B(props) {
return <div>Product B.</div>;
}
function Product(props) {
return <div>Product with name {props.params.productName}.</div>;
}
const router =
<Router> {/* Rendered components: */}
<Route path="about" component={Welcome} /> {/* <Welcome /> */}
<Route path="products" component={Products}> {/* <Products /> */}
<Route path="productA" component={A} /> {/* <Products><A /></Products> */}
<Route path="productB" component={B} /> {/* <Products><B /></Products> */}
<Route path=":productName" component={Product} /> {/* <Products><Product /></Products> */}
</Route>
<Redirect from="offers/::rest" to="products/::rest" />
</Router>
ReactDOM.render(router, document.getElementById("container"));
Matching algorithm
Routes are matched from the first to last and if a Route matches, its children are matched before its neighboring Route. Routes must consume the entire Url to match, therefore child Routes can unmatch a matching Route. As soon as a complete match is found, matching stops, so any other potentially matching Routes are ignored. Only Routes with no children can produce a complete match.
API
Router : Router extends React.Component
Root component. There can only be one Router
. Children of Router
can only be Route
and Redirect
.
Props
useHash : boolean (optional)
Use hash as url, default false.
ignoreBase : boolean (optional)
Ignore the <base>
tag, default false.
ignoreTrailingSlash : boolean (optional)
Ignore trailing slash, default false.
Route : Route extends React.Component
Represents one possible url application recognizes and responds to. Children of Route
can only be Route
and Redirect
. See tutorial above.
Note: Function onLeave
is called from the leaf Route
to the root Route
, onChange
and onEnter
are called after onLeave
in the opposite direction.
Props
path : string | function (optional)
Path this Route
represents. Use empty string to match trailing slash. If undefined, Route
always matches.
If path
is a string, this works (only for whole folders):
- :key - matches one folder from url, creates param with name
key
and the folder name as its value. - ::key - matches multiple folders, creates param.
- :::whatever - matches ":whatever" literally, can contain more colons.
All components rendered by Router will have property params
containing the same params. Custom params can be created using <Route params={{ paramName: "value"}} />
.
If path
is a function it will recieve this signature: path(pathArray, foldersConsumed) : pathReturnValue
pathArray : Array of string
Similar to location.pathname
.
foldersConsumed : number
Number of folders consumed so far. pathArray.slice(foldersConsumed)
will return array of folders yet to be consumed.
pathReturnValue : boolean | number | object | Array of undefined | string
If number, this is number of folders consumed by this Route
or -1 if it doesn't match. If this is array, it's array of param names or undefined if that folder should not create a param. If object, it has to have property foldersConsumed
that is either number or array and can have properties props
and params
- object with dynamic props.
component : function | React.Component | ReactClass (optional)
Component to render if Route
matches. Prop params
containing all params is injected into the component.
onEnter : function (optional)
Called when Route
is being entered.
onChange : function (optional)
Called when url is changed, but this Route
is already active and is not being left.
onLeave : function (optional)
Called when Route
is being left.
props : object (optional)
Props injected into component
of this or ancestor Route
. Only one component will receive the props.
params : object (optional)
Creates custom parameters. All components receive prop param
with the same params.
title : string (optional)
Webpage's title. Child Route
s can override this.
source : async function (optional)
Must return a Route
, loads asynchronously when the Route
matches. Async Route
s can have normal children that will be used until the source is successfully loaded. Page will be rerendered when the source is loaded without error. Note that if none of the child Routes
match, the async Route
won't match either and will not load source
. If an async Route
matches but is redirected, source
will also not load.
lazy : boolean (optional)
Only load source
after it is needed, default true.
displayPath : string (optional)
See generateUrls
.
Redirect : Redirect extends React.Component
Redirects to a different url.
Props
from : string | function (optional)
Path to match when redirecting.
to : string | function
Where to redirect. Consumes existing parameters instead of creating new ones. Use leading slash for absolute Url. If a function, it's only parameter will be result of currentUrl.split("/")
and the function must return next url as a string.
displayFrom : string (optional)
See generateUrls
.
displayTo : string (optional)
See generateUrls
.
server : Object
Only used on server for server-side rendering.
Fields
url : string
Last rendered url.
notFound : boolean
True if no Route
matches.
redirect : undefined | string
String if current url leads to redirection.
async loadAllRoutes(ReactDOMServer, router) : undefined
Loads all Route
s. NOOP after first use. In browser, use without parameters after router was rendered at least once.
Params
ReactDOMServer : ReactDOMServer
ReactDOMServer. Server-side only.
router : Router
Router to load. Server-side only.
Props
called : boolean
True if this function was already called. That it's false doesn't mean there are routes that are not yet loaded.
renderUrl(url, renderComponents) : string
Renders Router
with given url
. Sets server.url
, server.redirect
and server.notFound
. Use for server-side rendering. Must be called after loadAllRoutes()
.
Params
url : string
location.pathname.
renderComponents : boolean (optional)
Render components, default true. Set to false if you only want to know whether certain url exists or leads to redirection.
generateUrls(flat) : Object | Array of Object
Generates array of all urls this Router recognizes. If a Route has a string property 'displayPath', this value is preferred to 'path'. Function paths are converted to empty string unless 'displayPath' is specified.
Params
flat : boolean
If true, returns an array of { path: string, redirect: string | null, description: string }
.
If false, returns:
{ path: string
, fullPath: string
, redirect: string | null
, description: string | undefined
, children: Array of this
}
Server-side rendering
Example using Express:
const app = require("express")();
const ReactDOMServer = require("react-dom/server");
const ReactRouter9 = require("react-router9");
const router = require("./router.js"); // Exports a Router element.
ReactRouter9.loadAllRoutes(ReactDOMServer, router).then(() => app.listen(80));
app.use((req, res) => {
const string = ReactRouter9.renderUrl(req.url);
// If omitted, "404: Page not found." is rendered.
if (ReactRouter9.server.notFound) return res.sendStatus(404);
// If omitted, "Redirect to /new/url." is rendered with a clickable new url.
if (ReactRouter9.server.redirect) {
return res.redirect(ReactRouter9.server.redirect);
}
if (youUseTemplatingEngine) {
res.render("index", { string });
} else {
res.send("<html><head>...</head><body>" + string + "</body></html>");
}
});
Changelog
0.6.x
Added property <Route params=...>
. Routes can now set custom params.
0.5.x
Added function generateUrls()
, property loadAllRoutes.called
.
0.4.x
Top-level function loadAllRoutes()
is now usable in browsers, too.