Keep your state in sync with your multiple routers :sparkles::sparkles::sparkles::sparkles:
This is a fork of react-router-redux. It retains the same simple API as react-router-redux v5 but adds additional support for using multiple routers.
Use this as a drop-in replacement for react-router-redux when you have multiple routers that you want to sync with your redux store.
React Router Redux does not allow you to sync multiple routers to your redux store. See this issue: https://github.com/ReactTraining/react-router/issues/5663. This is understandable if you only have a single global router that is linked to your URL history. However, we believe that routers should be more extensible and generic than that. You may also want to use routing logic elsewhere to present components which you do not explicitly want stored in your browser's url history. We initially developed this fork as a pull request to generate conversation around the best approaches to implementing support for multiple routers. However, React Redux Router are not willing to support multiple routers, so we have now published this for anyone else who encounters this use case.
npm install --save react-router-redux-multi
npm install --save history
store
(Redux Store): The single Redux store in your application.children
(ReactElement): The root of your routes.history
(History): The history instance who's location maps to routesnamespace
(string): The namespace for to identify the history instance (default: 'default')Redux middle to intercept history actions and update the location in the reducer. Takes history instance as first argument, and optional namespace string to specify which history object to intercept.
Usage:
const middleeare =
const store = createStore(
combineReducers({
...reducers,
router: routerReducer
}),
applyMiddleware(middleware)
)
The redux reducer for storing router locations. Can store any number of history locations.
State is of the form:
{
location: {
default: history.location,
[namespace]: history.location
}
}
Usage:
import ConnectedRouter from '../ConnectedRouter'
import { routerReducer } from '../reducer'
store = createStore(combineReducers({
router: routerReducer
}))
This library exposes all History instances navigation methods (push, replace, go, goBack, goForward) as dispatchable redux actions. For detailed description of these methods look at the History documentation.
You can also create actions which target a specific history object by using the namespaced variants.
namespacedPush(namespace)(path, [state])
namespacedReplace(namespace)(path, [state])
namespacedGo(namespace)(n)
namespacedGoBack(namespace)()
namespacedGoForward(namespace)()
These actions will trigger state changes only on the history identified by that namespace. The same namespace should be passed to actions, as is passed to ConnectedRouter and routerMiddleware.
Or you can create an object with all namespaced actions via namespacedRouterActions(namespace)
.
Usage:
import { push, namespacedPush } from 'react-router-redux'
// Using store directly:
// to target the default router
store.dispatch(push('/foo'))
// or to target another reducer use namespaced actions
pushMemory = namespacedPush('memory')
store.dispatch(pushMemory('/foo'))
// Or via Connect
connect(
() => {}, // mapStateToProps
dispatch =>
bindActionCreators({
push: push,
pushToMemory: namespacedPush('/foo'),
}, dispatch);
)
Here's a basic idea of how it works:
import React from 'react'
import ReactDOM from 'react-dom'
import { createStore, combineReducers, applyMiddleware } from 'redux'
import { Provider } from 'react-redux'
import createHistory from 'history/createBrowserHistory'
import { Route } from 'react-router'
import { ConnectedRouter, routerReducer, routerMiddleware, push } from 'react-router-redux'
import reducers from './reducers' // Or wherever you keep your reducers
// Create a history of your choosing (we're using a browser history in this case)
const history = createHistory()
const memoryhistory = createMemoryHistory()
const memoryNamespace = 'memory'
// Build the middleware for intercepting and dispatching navigation actions
const middleware = [
routerMiddleware(history),
routerMiddleware(memoryhistory, memoryNamespace)
]
// Add the reducer to your store on the `router` key
// Also apply our middleware for navigating
const store = createStore(
combineReducers({
...reducers,
router: routerReducer
}),
applyMiddleware(middleware)
)
ReactDOM.render(
<Provider store={store}>
{ /* ConnectedRouter will use the store from Provider automatically */ }
{ /* This router is linked to your URL history */ }
<ConnectedRouter history={history}>
<div>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/topics" component={Topics}/>
</div>
</ConnectedRouter>
{ /* This router is stored in memory */ }
<ConnectedRouter history={memoryHistory} namespace={memoryNamespace}>
<div>
<Route path="/animationB" component={AnimationA}/>
<Route path="/animationA" component={AnimationB}/>
</div>
</ConnectedRouter>
</Provider>,
document.getElementById('root')
)