Coder Social home page Coder Social logo

redux-react-router's Introduction

License TypeScript Tests workflow

Redux React Router

A Redux binding for React Router

Main features

  • Synchronize router state with redux store through uni-directional flow (i.e. history -> store -> router -> components).
  • Supports React Router v6 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

Installation

Redux React Router requires React 16.8, React Redux 6.0, React Router 6.0 or later.

npm install --save @lagunovsky/redux-react-router
yarn add @lagunovsky/redux-react-router

Usage

Examples

Note: the history object provided to reducer, middleware, and component must be the same history object.

@reduxjs/toolkit

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 (
    <>
      <NavLink to={'/'} children={'Home'}/>
      <button type={'button'} onClick={onClickHandler} children={'Rand'}/>
    </>
  )
}

function App() {
  return (
    <Provider store={store}>
      <ReduxRouter history={history}>
        <Routes>
          <Route path={'*'} element={<Content/>}/>
        </Routes>
      </ReduxRouter>
    </Provider>
  )
}

redux.createStore and custom selector

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<typeof store.getState>

const routerSelector: ReduxRouterSelector<State> = (state) => state.navigator

function App() {
  return (
    <Provider store={store}>
      <ReduxRouter history={history} routerSelector={routerSelector}>
        <Routes>
          <Route path={'*'} element={<div/>}/>
        </Routes>
      </ReduxRouter>
    </Provider>
  )
}

API

Types

type ReduxRouterProps = {
  history: History
  basename?: string
  children?: React.ReactNode
  routerSelector?: ReduxRouterSelector 
}
type ReduxRouterState = {
  location: history.Location
  action: history.Action
}

Constants

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) => 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.

createRouterReducerMapObject(history: History) => {router: Reducer<ReduxRouterState>}

Creates a reducer map object that stores location updates from history.

createRouterReducer(history: History) => Reducer<ReduxRouterState>

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, you must add a selector (state: State) => ReduxRouterState to your <ReduxRouter/> as routerSelector prop.

reduxRouterSelector(state: State): ReduxRouterState

Selector that returns location updates from history.

Action creators

Same as history methods

  • push
  • replace
  • 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

Migrate from Connected React Router

- import { connectRouter } from 'connected-react-router'
+ import { createRouterReducer } from '@lagunovsky/redux-react-router'

- export const routerReducer = connectRouter(history)
+ export const routerReducer = createRouterReducer(history)
- import { routerMiddleware } from 'connected-react-router'
+ import { createRouterMiddleware } from '@lagunovsky/redux-react-router'

- export const routerMiddleware = routerMiddleware(history)
+ export const routerMiddleware = createRouterMiddleware(history)
- import { ConnectedRouter } from 'connected-react-router'
+ import { ReduxRouter } from '@lagunovsky/redux-react-router'

- <ConnectedRouter history={history} />
+ <ReduxRouter history={history} />
- import { RouterState } from 'connected-react-router'
+ import { ReduxRouterState } from '@lagunovsky/redux-react-router'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.