A Redux binding for React Router v6
npm install @lagunovsky/redux-react-router!License
!TypeScript
!Tests workflow
Redux React Router
======================
A Redux binding for React Router
- Main features
- Installation
- Usage
- - Examples
- - API
- Migrate from Connected React Router
- Synchronize router state with redux store through uni-directional flow (i.e. history -> store -> router -> components).
- Supports React Router v7 and History v5
- Supports functional component hot reloading while preserving state.
- Dispatching of history methods (push, replace, go, back, forward) works for both redux-thunk
and redux-saga.
- Nested children can access routing state such as the current location directly with react-redux's connect.
- Supports time traveling in Redux DevTools.
- TypeScript
Redux React Router requires React 16.8, React Redux 6.0, React Router 6.0 or later.
``shell`
npm install --save @lagunovsky/redux-react-router
`shell`
yarn add @lagunovsky/redux-react-router
Note: the history object provided to reducer, middleware, and component must be the same history object.
#### @reduxjs/toolkit
`typescript jsx
import { createRouterMiddleware, createRouterReducerMapObject, push, ReduxRouter } from '@lagunovsky/redux-react-router'
import { configureStore } from '@reduxjs/toolkit'
import { createBrowserHistory } from 'history'
import React from 'react'
import { createRoot } from 'react-dom/client'
import { Provider, useDispatch } from 'react-redux'
import { Route, Routes } from 'react-router'
import { NavLink } from 'react-router-dom'
const history = createBrowserHistory()
const routerMiddleware = createRouterMiddleware(history)
const store = configureStore({
reducer: createRouterReducerMapObject(history),
middleware: (getDefaultMiddleware) => getDefaultMiddleware().prepend(routerMiddleware),
})
function Content() {
const dispatch = useDispatch()
const onClickHandler = () => {
const action = push(Date.now().toString())
dispatch(action)
}
return (
<>
function App() {
return (
)
}
`
#### redux.createStore and custom selector
`typescript jsx
import { createRouterMiddleware, createRouterReducer, push, ReduxRouter, ReduxRouterSelector } from '@lagunovsky/redux-react-router'
import { createBrowserHistory } from 'history'
import React from 'react'
import { createRoot } from 'react-dom/client'
import { Provider, useDispatch } from 'react-redux'
import { Route, Routes } from 'react-router'
import { NavLink } from 'react-router-dom'
import { applyMiddleware, combineReducers, compose, createStore } from 'redux'
const history = createBrowserHistory()
const routerMiddleware = createRouterMiddleware(history)
const rootReducer = combineReducers({ navigator: createRouterReducer(history) })
const store = createStore(rootReducer, compose(applyMiddleware(routerMiddleware)))
type State = ReturnType
const routerSelector: ReduxRouterSelector
function App() {
return (
)
}
`
#### Types
`typescript jsx`
type ReduxRouterProps = {
history: History
basename?: string
children?: React.ReactNode
routerSelector?: ReduxRouterSelector
}
`typescript jsx`
type ReduxRouterState = {
location: history.Location
action: history.Action
}
#### Constants
`typescript jsx`
const ROUTER_REDUCER_MAP_KEY = 'router'
const ROUTER_CALL_HISTORY_METHOD = '@@router/CALL_HISTORY_METHOD'
const ROUTER_ON_LOCATION_CHANGED = '@@router/ON_LOCATION_CHANGED'
#### createRouterMiddleware(history: History, options?: RouterMiddlewareOptions) => Middleware
A middleware you can apply to your Redux store to capture dispatched actions created by the action creators.
It will redirect those actions to the provided history instance.
If you need the middleware to pass the action on after being handled, you can provide the hasNextCall option as true.
#### createRouterReducerMapObject(history: History) => {router: Reducer
Creates a reducer map object that stores location updates from history.
#### createRouterReducer(history: History) => Reducer
Creates a reducer function that stores location updates from history.
Note: If you create a reducer with a key other than ROUTER_REDUCER_MAP_KEY, (state: State) => ReduxRouterState
you must add a selector to your as routerSelector prop.
#### reduxRouterSelector(state: State): ReduxRouterState
Selector that returns location updates from history.
Same as history methods
- pushreplace
- go
- back
- forward
-
By default, history methods calls in middleware are wrapped in a queueMicrotask. If you want to avoid it, please use the following methods:
- pushStraight replaceStraight
- goStraight
- backStraight
- forwardStraight
-
`diff
- import { connectRouter } from 'connected-react-router'
+ import { createRouterReducer } from '@lagunovsky/redux-react-router'
- export const routerReducer = connectRouter(history)
+ export const routerReducer = createRouterReducer(history)
`
`diff
- import { routerMiddleware } from 'connected-react-router'
+ import { createRouterMiddleware } from '@lagunovsky/redux-react-router'
- export const routerMiddleware = routerMiddleware(history)
+ export const routerMiddleware = createRouterMiddleware(history)
`
`diff
- import { ConnectedRouter } from 'connected-react-router'
+ import { ReduxRouter } from '@lagunovsky/redux-react-router'
-
+
`
`diff``
- import { RouterState } from 'connected-react-router'
+ import { ReduxRouterState } from '@lagunovsky/redux-react-router'