npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

async-react-router

v2.1.1

Published

Client side react router with async. It like next.js!

Readme

async-react-router

Build Status npm version Coverage Status dependencies Status Commitizen friendly

Async-react-router is react router that can easily get initial props using async/await or promise.
If you use this library, You can get the initial props like Next.js.
And this library works only on client also.

Version

|Version|React|RxJS|README| |:---:|:---:|:---:|:---:| |2.0|15.X or 16.X|6.X|Link| |1.0|15.X or 16.X|5.X|Link|

In order to correspond to dynamic import, v2 has breaking change from v1.

Features

  • Support getInitialProps() like Next.js.
  • Support only on client-side.
  • Support sever-side rendering.
  • Support URL parameters.
  • Support history package. The following history type is supported.
    • Hash history
    • Browser history
    • Memory history
  • Support dynamic import.
  • No depend on react-router.

Demo

Installation

Async-react-router has peer dependencies of [email protected] which will have to be installed.

npm install async-react-router react react-dom rxjs --save

Example

import React from 'react';
import { render } from "react-dom";
import { createRouter } from "async-react-router";

function sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}

class Home extends React.Component {
    static initialPropsWillGet(attributes, prevAttributes) {
        console.log('Taking a break...');
    }
    
    static async getInitialProps(attributes, prevAttributes) {
        await sleep(5000);
        return {
            message: 'Home is five second sleep.'
        };
    }
    
    static initialPropsDidGet(props, prevProps) {
        console.log('Five second later');
    }

    render() {
        return (
            <div>
                <h2>Home</h2>
                <dl>
                    <dt>Message</dt>
                    <dd>{this.props.message}</dd>
                </dl>
                <ul>
                    <li><Link to="/page">Page Index</Link></li>
                    <li><Link to="/page/1">Page 1</Link></li>
                </ul>
            </div>
        );
    };
}

const router = createRouter();
router.route("/", Home);
router.run((Root) => {
  render(<Root/>, document.getElementById("app"));
});

API

createRouter()

createRouter() generates router instance. Default history type is Hash history.

import { createRouter } from "async-react-router";

const router = createRouter();

If you want to change history type to browser history or memory history, you can define below.

// Browser history
import { createRouter, createBrowserHistory } from "async-react-router";
const router = createRouter(createBrowserHistory());

// Memory history
import { createRouter, createMemoryHistory } from "async-react-router";
const router = createRouter(createMemoryHistory());

router.route(path, component, name)

Route links a path and a component.

  • path - Any valid URL path that path-to-regexp understands. Required.
  • component - A react component to render only when the location matches. Required.
  • name - Route name. You can use at Request.name(name), or URL.name(name). Optional.
import React from 'react';
import { createRouter } from 'async-react-router';
import Home from "./components/Home";

const router = createRouter();
router.route("/", Home, "Home");
router.run((Root) => {
  render(<Root/>, document.getElementById("app"));
});

router.asyncRoute(path, () => promise, name)

If you want to use dynamic import, You can define using asyncRoute().

  • path - Any valid URL path that path-to-regexp understands. Required.
  • component - A react component to render only when the location matches. Required.
  • name - Route name. You can use Request.name(name), or URL.name(name). Optional.
import { createRouter } from 'async-react-router';

const router = createRouter();
router.asyncRoute("/", () => import("./components/Home"), "Home");
router.run((Root) => {
  hydrate(<Root />, document.getElementById("app"));
});

router.run((RootComponent) => void)

run generates the root component.

import { createRouter } from 'async-react-router';
import Home from "./components/Home";

const router = createRouter();
router.route("/", Home, "Home");
router.run((Root) => {
  render(<Root />, document.getElementById("app"));
});

If you want to add parameters, you can define parameters with the root component parameters.

import { createRouter } from 'async-react-router';
import Home from "./components/Home";

const router = createRouter();
router.route("/", Home, "Home");
router.run((Root) => {
  render(<Root any={"any"}/>, document.getElementById("app"));
});

router.setFirstComponent(component)

If you want to render any component at first rendering, you can define component.

import { createRouter } from 'async-react-router';
function FirstComponent() {
  return (
    <div className="text-center" style={{margin: "100px 0"}}>
      <i className="fa fa-cog fa-spin fa-5x fa-fw"/>
    </div>
  )
}

const router = createRouter();

// Set first rendered component.
router.setFirstComponent(FirstComponent);

router.run((Root) => {
  hydrate(<Root />, document.getElementById("app"));
});

router.setInitialProps(parameters)

If you want to render server-side, you will want to give initial data. In that case, you can set initial data with setInitialProps().
When you use setInitialProps(), initialPropsWillGet() and initialPropsDidGet() are not called for the first time.
Only getInitialProps() is called.

import { createRouter } from 'async-react-router';

const router = createRouter();

// Set data from server.
router.setInitialProps(
  JSON.parse(document.getElementById("initial-props").innerText);
);

router.run((Root) => {
  hydrate(<Root/>, document.getElementById("app"));
});

Link

<Link> makes a request event and renders component matching route path.

import { Link } from 'async-react-router';

<Link to="/">Home</Link>

Route component

component.initialPropsWillGet(attributes, prevAttributes): void

Route component can have initialPropsWillGet().
initialPropsWillGet() is invoked immediately before mounting occurs. It is called before getInitialProps() This method is static.

initialPropsWillGet() has arguments below.

  • attributes - Current route attributes.
    • pathname - String of the current path.
    • params - Object with the parsed url parameter. Defaults to {}.
  • prevAttributes - Previous route attributes. Defaults to {}.
    • pathname - String of the previous path.
    • params - Object with the parsed url parameter at previous page. Defaults to {}.

async/await is not supported.

component.getInitialProps(attributes, prevAttributes): Object

Route component can have getInitialProps() that can use async/await.
getInitialProps() perform the rendering after promise has been resolved, The resolved data can be retrieved as props of component. This method is static.

And getInitialProps() has arguments below.

  • attributes - Current route attributes.
    • pathname - String of the current path.
    • params - Object with the parsed url parameter. Defaults to {}.
  • prevAttributes - Previous route attributes. Defaults to {}.
    • pathname - String of the previous path.
    • params - Object with the parsed url parameter at previous page. Defaults to {}.
import { createRouter } from 'async-react-router';

class User extends React.Component {
    static async getInitialProps(attributes, prevAttributes) {
        console.log(attributes.params.userId);
        return { 
          data: "Get initial props!!" 
        };
    }
    
    render() {
        return (
            <div>
                <div>UserId: {this.props.params.userId}</div>
                <div>Data: {this.props.data}</div>
            </div>
        );
    }
}

const router = createrRouter();
router.route("/user/:userId", User);
router.run((Root) => {
  render(<Root/>, document.getElementById("app"));
});

component.initialPropsDidGet(props, prevProps): void

Route component can have initialPropsDidGet().
initialPropsDidGet() is called after getInitialProps().
If more than one promise is pending, Async-react-router gets only data of last executed promise.
For this reason, initialPropsDidGet() is executed only when the last promise is resolved. This method is static.

initialPropsDidGet() has arguments.

  • props - Current props of components defined at route.
    • pathname - String of the current path.
    • params - Object with the parsed url parameter. Defaults to {}.
    • {data} - Data retrieved using getInitialProps().
  • prevProps - Previous props of components defined at route. First rendering to {}.
    • pathname - String of the previous path.
    • params - Object with the parsed url parameter at previous page. Defaults to {}.
    • {data} - Data retrieved using getInitialProps().

async/await is not supported.

Request

Request.to(path)

When you want to push next request, you can use to of Request.

  • path - String of next path.
import { Request } from 'async-react-router';

Request.to('/next'); // Change url to `#/next`.

Request.name(routeName, urlParameters)

You can make next request from the name defined at route.

  • routeName - Route name for next request.
  • urlParameters - Object of next url parameters. Optional.
import React from 'react';
import { render } from 'react-dom';
import { createRouter, Request } from 'async-react-router';

class User extends React.Component {
    render() { return (<div>{this.props.params.userId}</div>); };
}

const router = createRouter();
router.route("/user/:userId", User, "User");
router.run((Root) => {
  render(<Root/>, document.getElementById("app"));
});

Request.name("User", {userId: 1}); // Change url to `#/user/1`.

Request.isActive(path)

When you want to check path, you can use isActive() of Request.

import { Request } from 'async-react-router';

// When current path is `/`...
Request.isActive('/');     // true
Request.isActive('/path'); // false

URL

URL.to(path)

When you want to make path, you can use to of URL.

  • path - String of path.
import { URL } from 'async-react-router';

URL.to('/next'); // String `#/next`.

URL.name(routeName, urlParameters)

You can make URL from the name defined at route.

  • routeName - Route name.
  • urlParameters - Object of url parameter, if it requires.
import React from 'react';
import { render } from 'react-dom';
import { createRouter, URL } from 'async-react-router';

class User extends React.Component {
    render() { return (<div>{this.props.params.userId}</div>); };
}

const router = createRouter();
router.route("/user/:userId", User, "User");
router.run((Root) => {
  render(<Root/>, document.getElementById("app"));
});

URL.name("User", {userId: 1}); // String `#/user/1`.

Server Side Rendering

Async-react-router supports server-side rendering.

  • SSR.createServerRouter() generates server-side router instance.
  • You can deal with SSR just by changing createRouter() to SSR.createRouter() on client side.
  • It is also possible to obtain resolved data on the server side via HTML on client-side.

Server Side

SSR.createServerRouter()

SSR.createServerRouter() generates server-side router instance. Supported history type is only memory history. serverRouter instance has route() and asyncRoute() also.

import { SSR } from "async-react-router";

app.get("*", function(req, res) {
  function setRoutes(router) {
    router.route("/", IndexPage);
    router.asyncRoute("/user", () => import("./UserPage"));
  }
  
  const serverRouter = SSR.createServerRouter();
  setRoutes(serverRouter);
}

serverRouter.runUsingPathname(pathname, callback(RootComponent, data) => void)

serverRouter.runUsingPathname() generates root component and initial data.
getInitialProps() and initialPropsWillGet(), initialPropsDidGet() are not called for the first time.

import ejs from "ejs";
import React from "react";
import ReactDOMServer from "react-dom/server";
import express from "express";
import { SSR } from "async-react-router";
import fs from "fs";

const app = express();

app.get("*", function(req, res) {
  // Please make another file and import.
  function setRoutes(router) {
    router.route("/", IndexPage);
    router.asyncRoute("/user", () => import("./UserPage"));
  }
  
  const serverRouter = SSR.createServerRouter();
  setRoutes(serverRouter);
  serverRouter.runUsingPathname(req.url, (Root, data) => {
    fs.readFile("index.html", function(err, result) {
          const compiled = ejs.compile(result.toString("utf8"), "utf8");
          const html = compiled({
            component: ReactDOMServer.renderToString(<Root/>),
            data: data
          });
    
          res.write(html);
          res.end();
        });
  });
}

Client Side

SSR.createRouter()

SSR.createrRouter () generates a router instance with the same functionality as createrRouter (). The only difference is history type.
Supported history type is only browser history. Hash History and Memory History cannot be used.

import React from "react";
import { hydrate } from "react-dom";
import { SSR } from "async-react-router";

// Please make another file and import.
function setRoutes(router) {
    router.route("/", IndexPage);
    router.asyncRoute("/user", () => import("./UserPage"));
}

const router = SSR.createRouter();
setRoutes(router);
router.setInitialProps(JSON.parse(document.getElementById("initial-props").innerText));
router.run((Root) => {
  hydrate(<Root/>, document.getElementById("app"));
});

This is the same process as below.

import React from "react";
import { hydrate } from "react-dom";
import { createRouter, createBrowserHistory } from "async-react-router";

// Please make another file and import.
function setRoutes(router) {
    router.route("/", IndexPage);
    router.asyncRoute("/user", () => import("./UserPage"));
}

const router = createRouter(createBrowserHistory());
setRoutes(router);
router.setInitialProps(JSON.parse(document.getElementById("initial-props").innerText));
router.run((Root) => {
  hydrate(<Root/>, document.getElementById("app"));
});

Thanks for the inspiration

License

MIT