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 🙏

© 2024 – Pkg Stats / Ryan Hefner

universal-redux-router

v2.2.0

Published

A router that turns URL params into first-class Redux state and runs action creators on navigation

Downloads

35

Readme

Universal Redux Router

A router that turns URL params into first-class Redux state and runs action creators on navigation.


Test status Dependencies status

Navigation

Motivation

If you're a good web citizen each part of your app can be linked to with a URL. These URLs often contain state either as part of the path name or within the query string.

/users/782/posts?page=2&tags[]=coding,making

In the above example, we have the following state:

{
  id: 782,
  page: 2,
  tags: [ 'coding', 'making' ],
}

I want that state in my Redux store!

Features

Extracts state from URLs

Universal Redux Router extracts state from a URL and adds it as first-class state to your Redux store.

It achieves this by allowing you to attach Redux action creators to your routes.

const routes = [
  [
    'users/:id/posts',
    {
      id: updateId,
      page: updatePage,
      tags: updateTags,
    },
    <UsersPosts />,
  ],
];

In the above example, we have one route defined that will match /users/<anything>/posts. It has three Redux action creators attached updateId, updatePage and updateTags.

When a user navigates to a URL, the action creators associated with the matching route are called with the appropriate part of the URL.

For example, navigating to /users/782/posts?page=2&tags[]=coding,making will result in the following function calls:

  • updateId( '782' )
  • updatePage( '2' )
  • updateTags([ 'coding', 'making' ])

The returned actions are then used to calculate the new state of the Redux store.

Runs action creators after calculating new state

On top of running action creators to extract state from URL params, Universal Redux Router allows you to define action creators to run after the new state has been calculated.

const routes = [
  [
    'users/:id/posts',
    {
      id: updateId,
      page: updatePage,
      tags: updateTags,
      after: [ postsUpdating, getPosts, postsUpdated ],
    },
    <UsersPosts />,
  ],
];

In the above example the action creators updateId, updatePage and updateTags are run first. The returned actions are used to calculate the new state.

The after action creators are then run in sequence, each called in turn with the updated state.

Handles async action creators

Both URL param action creators and after action creators can return promises.

The after action creators will not be called until all URL param action creators have resolved and the new state has been calculated.

Each one of the after action creators will not be called until the previous after action creator has been resolved and the new state calculated.

Routing on server and client

As the name implies, Universal Redux Router is designed specifically to work the same on both server and client.

No need for environment specific code. Phew!

Examples

Installation

npm install universal-redux-router

Usage

Router

The Router component handles which component will be displayed by taking the url property of your Redux store and your routes array.

It matches a route and returns the component defined within that route.

import { Router } from 'universal-redux-router';

const Root = () => (
  <Provider store={ store }>
    <Router routes={ routes } />
  </Provider>
);

routerMiddleware

You must use routerMiddleware in your Redux middleware stack. This listens for the CHANGE_PAGE_TO action, matches a route and then makes a list of additional actions we need to dispatch.

It also includes a few conveniences like updating scroll position on navigation and handling browser history.

import { routerMiddleware } from 'universal-redux-router';

const middleware = applyMiddleware( routerMiddleware( routes ));

return createStore( reducer, state, middleware );

routerReducer

Instead of using Redux's combineReducers to create your root reducer, you must use routerReducer. It has the same API as combineReducers.

routerReducer uses combineReducers under the hood for all incoming actions apart from CHANGE_PAGE_TO. When it receives CHANGE_PAGE_TO it iterates over the list of associated actions to calculate state.

import { routerReducer } from 'universal-redux-router';

const reducer = routerReducer( reducers );

changePageTo

The changePageTo Redux action creator creates the CHANGE_PAGE_TO action. It is how we navigate using Universal Redux Router.

It can either take an array of data, or a URL string.

import { changePageTo } from 'universal-redux-router';

store.dispatch(
  changePageTo([ 'users', id, 'posts', { page, tags }])
);

store.dispatch(
  changePageTo( `/users/${ id }/string?page=${ page }&tags[]=${ tags.join( ',' )}` )
);

Link

The Link component is used to create an HTML anchor element that has changePageTo handling built in. This means you don't have to worry about onClick events or having to directly call changePageTo.

Like changePageTo it accepts both an array of data or a URL string as its to prop.

import { Link } from 'universal-redux-router';

<Link to={[ 'users', id, 'posts', { page, tags }]}>
  User posts
</Link>

<Link to={ `/users/${ id }/string?page=${ page }&tags[]=${ tags.join( ',' )}` }>
  User posts
</Link>

getState

The getState helper does exactly what the the router does on a CHANGE_PAGE_TO action, but without any dispatch calls, and therefore without the need for a Redux store.

This means we can use it to calculate the initial state to create our Redux store.

We can also use it on both server and client to avoid passing state between the two.

import { getState } from 'universal-redux-router';

getState( url, routes, reducer ).then( state => {
  const store = createStore( reducer, state, middleware );
});

Help make this better

Issues and pull requests gratefully received!

I'm also on twitter @colinmeinke.

Thanks :star2:

Thanks

License

ISC.