Skip to content

mksarge/redux-first-routing

Repository files navigation

Redux-First Routing npm version build status

Achieve client-side routing the Redux way:

  • Read location data from the store.
  • Update the location by dispatching navigation actions.
  • Let middleware handle the side-effect of history navigation.

Learn more: An Introduction to the Redux-First Routing Model

Redux-first routing

Ideology

This library wraps history and provides a minimal, framework-agnostic base for accomplishing Redux-first routing. It does not provide the actual router component.

Instead, you can pair it with a compatible router to create a complete routing solution. If you're coming from React Router, you might compare this package to react-router-redux.

Installation

Install the library from npm:

npm install --save redux-first-routing 

Or, use the following script tag to access the latest UMD build on window.ReduxFirstRouting:

<script src="https://unpkg.com/redux-first-routing/dist/redux-first-routing.min.js"></script>

Usage

Basic Usage

import { combineReducers, applyMiddleware, createStore } from 'redux' import { createBrowserHistory, routerReducer, routerMiddleware, startListener, push } from 'redux-first-routing' import { otherReducers } from './reducers' // Create the history object const history = createBrowserHistory() // Add the reducer, which adds location state to the store const rootReducer = combineReducers({ ...otherReducers, router: routerReducer // Convention is to use the "router" property }) // Build the middleware, which intercepts navigation actions and calls the corresponding history method const middleware = routerMiddleware(history) // Create the store const store = createStore(rootReducer, {}, applyMiddleware(middleware)) // Start the history listener, which automatically dispatches actions to keep the store in sync with the history startListener(history, store) // Now you can read the location from the store! let currentLocation = store.getState().router.pathname // You can also subscribe to changes in the location! let unsubscribe = store.subscribe(() => { let previousLocation = currentLocation currentLocation = store.getState().router.pathname if (previousLocation !== currentLocation) { console.log(`Location changed from ${previousLocation} to ${currentLocation}`) // Render your application reactively here (optionally using a compatible router) } }) // And you can dispatch navigation actions from anywhere! store.dispatch(push('/about'))

State Shape

There are dozens of ways to design the state shape of the location data, and this project must by nature choose an opinionated design:

// URL: www.example.com/nested/path?with=query#and-hash { router: { pathname: '/nested/path/', search: '?with=query', queries: { with: 'query' }, hash: '#and-hash' }, ... // other redux state }

The query-string package is used internally to parse the search string into the queries object.

Compatible Routers

For a router to work seamlessly with redux-first-routing, it must not be tightly coupled to the browser history/navigation code. The following libraries meet that criteria by providing router components that focus solely on the routing and/or rendering part:

For examples of usage, see Recipies. To add to this list, feel free to send a pull request.

Documentation

Credits

The concept of "Redux-first routing" isn't particularly new — everything in this library has existed in one form or another across various other Redux routing libraries and packages. You may find a long list of similar projects (some of which may be classified as Redux-first routing libraries) here:

Notable influences:

Contributing

Contributions are welcome and are greatly appreciated! 🎉

Feel free to file an issue, start a discussion, or send a pull request.

License

MIT

Releases

No releases published

Packages

No packages published