0.6.2 • Published 9 years ago

react-router9 v0.6.2

Weekly downloads
-
License
MIT
Repository
github
Last release
9 years ago

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 Links (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 Routes and Redirects 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 Routes 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 Routes can override this.

source : async function (optional)

Must return a Route, loads asynchronously when the Route matches. Async Routes 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 Routes. 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.

0.6.2

9 years ago

0.6.1

9 years ago

0.6.0

9 years ago

0.5.0

9 years ago

0.4.3

9 years ago

0.4.2

9 years ago

0.4.1

9 years ago

0.4.0

9 years ago