Convert Figma logo to code with AI

supasate logoconnected-react-router

A Redux binding for React Router v4

4,725
594
4,725
175

Top Related Projects

Declarative routing for React

6,895

2,067

🧭 Declarative, asynchronous routing for React.

6,666

🥢 A minimalist-friendly ~2.1KB routing for React and Preact

🎖 seamless redux-first routing -- just dispatch actions

Quick Overview

Connected React Router is a Redux binding for React Router v4 and v5. It synchronizes your Redux store with your React Router state, allowing you to control your routing via Redux actions and access routing state in your Redux store.

Pros

  • Seamless integration between React Router and Redux
  • Enables time-travel debugging for route changes
  • Allows for declarative routing configuration
  • Provides a consistent way to manage routing state in Redux

Cons

  • Adds complexity to the application architecture
  • May have a slight performance overhead due to additional state management
  • Requires understanding of both Redux and React Router concepts
  • Not necessary for simpler applications with basic routing needs

Code Examples

  1. Configuring the store with Connected React Router:
import { createBrowserHistory } from 'history'
import { applyMiddleware, compose, createStore } from 'redux'
import { routerMiddleware } from 'connected-react-router'
import createRootReducer from './reducers'

const history = createBrowserHistory()

const store = createStore(
  createRootReducer(history),
  compose(
    applyMiddleware(
      routerMiddleware(history)
    )
  )
)
  1. Using ConnectedRouter component:
import { Provider } from 'react-redux'
import { ConnectedRouter } from 'connected-react-router'
import App from './App'

ReactDOM.render(
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <App />
    </ConnectedRouter>
  </Provider>,
  document.getElementById('root')
)
  1. Dispatching navigation actions:
import { push } from 'connected-react-router'

// In a component or action creator
dispatch(push('/home'))

Getting Started

  1. Install the package:

    npm install connected-react-router
    
  2. Create a history object:

    import { createBrowserHistory } from 'history'
    const history = createBrowserHistory()
    
  3. Add the connectRouter reducer to your root reducer:

    import { combineReducers } from 'redux'
    import { connectRouter } from 'connected-react-router'
    
    const rootReducer = combineReducers({
      router: connectRouter(history),
      // ... other reducers
    })
    
  4. Use ConnectedRouter instead of BrowserRouter:

    import { ConnectedRouter } from 'connected-react-router'
    
    ReactDOM.render(
      <Provider store={store}>
        <ConnectedRouter history={history}>
          <App />
        </ConnectedRouter>
      </Provider>,
      document.getElementById('root')
    )
    

Competitor Comparisons

Declarative routing for React

Pros of React Router

  • More actively maintained and widely adopted in the React community
  • Offers a more comprehensive routing solution with features like nested routes and route-based code splitting
  • Provides better integration with modern React features like hooks and context

Cons of React Router

  • Requires more setup and configuration compared to Connected React Router
  • May have a steeper learning curve for developers new to React routing
  • Doesn't provide built-in Redux integration, which might be a drawback for some projects

Code Comparison

React Router:

import { BrowserRouter, Route, Switch } from 'react-router-dom';

<BrowserRouter>
  <Switch>
    <Route path="/home" component={Home} />
    <Route path="/about" component={About} />
  </Switch>
</BrowserRouter>

Connected React Router:

import { ConnectedRouter } from 'connected-react-router';
import { Route, Switch } from 'react-router';

<ConnectedRouter history={history}>
  <Switch>
    <Route path="/home" component={Home} />
    <Route path="/about" component={About} />
  </Switch>
</ConnectedRouter>

Both libraries provide similar basic routing functionality, but React Router offers more flexibility and features for complex routing scenarios. Connected React Router, on the other hand, focuses on seamless integration with Redux, making it a good choice for projects heavily reliant on Redux for state management.

6,895

Pros of reach/router

  • Simpler API and easier to use, especially for beginners
  • Built-in accessibility features for screen readers
  • Supports relative routing, making nested routes easier to manage

Cons of reach/router

  • Less integration with Redux, which may be a drawback for complex applications
  • Fewer advanced features compared to connected-react-router
  • Limited community support and updates

Code Comparison

reach/router:

import { Router } from "@reach/router"

<Router>
  <Home path="/" />
  <Dashboard path="dashboard" />
  <Profile path="profile/:id" />
</Router>

connected-react-router:

import { ConnectedRouter } from 'connected-react-router'

<ConnectedRouter history={history}>
  <Switch>
    <Route exact path="/" component={Home} />
    <Route path="/dashboard" component={Dashboard} />
    <Route path="/profile/:id" component={Profile} />
  </Switch>
</ConnectedRouter>

Both libraries provide routing solutions for React applications, but they differ in their approach and feature set. reach/router focuses on simplicity and accessibility, making it a good choice for smaller projects or those prioritizing ease of use. connected-react-router, on the other hand, offers tighter integration with Redux and more advanced features, making it suitable for complex applications with state management requirements.

2,067

🧭 Declarative, asynchronous routing for React.

Pros of Navi

  • Built-in code splitting and async data loading support
  • Declarative routing with a focus on type safety
  • Supports server-side rendering out of the box

Cons of Navi

  • Smaller community and ecosystem compared to Connected React Router
  • Steeper learning curve for developers familiar with React Router
  • Less integration with Redux, which may be a drawback for some projects

Code Comparison

Navi:

import { createBrowserNavigation } from 'navi';
import { Router, View } from 'react-navi';

const routes = {
  '/': () => <HomePage />,
  '/about': () => <AboutPage />,
};

const navigation = createBrowserNavigation({ routes });

Connected React Router:

import { ConnectedRouter } from 'connected-react-router';
import { Route, Switch } from 'react-router-dom';

<ConnectedRouter history={history}>
  <Switch>
    <Route exact path="/" component={HomePage} />
    <Route path="/about" component={AboutPage} />
  </Switch>
</ConnectedRouter>

Both libraries offer routing solutions for React applications, but Navi focuses on declarative routing with built-in code splitting and async data loading. Connected React Router, on the other hand, provides tighter integration with Redux and follows a more traditional React Router approach. The choice between the two depends on project requirements and developer preferences.

6,666

🥢 A minimalist-friendly ~2.1KB routing for React and Preact

Pros of wouter

  • Lightweight and minimalistic (1kB gzipped) compared to connected-react-router
  • No external dependencies, works with any state management solution
  • Simple API with hooks-based approach

Cons of wouter

  • Less feature-rich than connected-react-router
  • May require additional setup for complex routing scenarios
  • Limited integration with Redux ecosystem

Code Comparison

wouter:

import { Route, Switch } from "wouter";

function App() {
  return (
    <Switch>
      <Route path="/home" component={Home} />
      <Route path="/about" component={About} />
    </Switch>
  );
}

connected-react-router:

import { ConnectedRouter } from "connected-react-router";
import { Route, Switch } from "react-router";

function App({ history }) {
  return (
    <ConnectedRouter history={history}>
      <Switch>
        <Route path="/home" component={Home} />
        <Route path="/about" component={About} />
      </Switch>
    </ConnectedRouter>
  );
}

The code comparison shows that wouter has a simpler setup, while connected-react-router requires additional configuration with the Redux store and history object. wouter's approach is more straightforward, especially for smaller projects or those not using Redux. However, connected-react-router offers tighter integration with Redux and more advanced routing features for complex applications.

🎖 seamless redux-first routing -- just dispatch actions

Pros of redux-first-router

  • More flexible routing system, allowing for complex routing scenarios
  • Better integration with Redux, treating routes as first-class citizens in the state
  • Supports server-side rendering out of the box

Cons of redux-first-router

  • Steeper learning curve due to its unique approach to routing
  • Less conventional routing setup, which may be unfamiliar to developers used to traditional routing libraries
  • Requires more boilerplate code for basic routing scenarios

Code Comparison

redux-first-router:

const routesMap = {
  HOME: '/',
  USER: '/user/:id',
  CATEGORY: '/category/:name'
}

const reducer = combineReducers({ location: locationReducer })
const store = createStore(reducer, applyMiddleware(thunk, routerMiddleware))

connected-react-router:

import { ConnectedRouter } from 'connected-react-router'

const store = createStore(
  createRootReducer(history),
  applyMiddleware(routerMiddleware(history))
)

<Provider store={store}>
  <ConnectedRouter history={history}>
    {/* Your routes */}
  </ConnectedRouter>
</Provider>

Both libraries aim to integrate routing with Redux, but they take different approaches. redux-first-router focuses on treating routes as actions and part of the Redux state, while connected-react-router provides a more traditional routing approach with tighter Redux integration. The choice between them depends on the specific needs of your project and your preferred routing philosophy.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Breaking change in v5.0.0! Please read How to migrate from v4 to v5/v6.

v6.0.0 requires React v16.4.0 and React Redux v6.0 / v7.0.

Connected React Router Build Status Open Source Helpers

A Redux binding for React Router v4 and v5

Main features

:sparkles: Synchronize router state with redux store through uni-directional flow (i.e. history -> store -> router -> components).

:gift: Supports React Router v4 and v5.

:sunny: Supports functional component hot reloading while preserving state (with react-hot-reload).

:tada: Dispatching of history methods (push, replace, go, goBack, goForward) works for both redux-thunk and redux-saga.

:snowman: Nested children can access routing state such as the current location directly with react-redux's connect.

:clock9: Supports time traveling in Redux DevTools.

:gem: Supports Immutable.js

:muscle: Supports TypeScript

Installation

Connected React Router requires React 16.4 and React Redux 6.0 or later.

npm install --save connected-react-router

Or

yarn add connected-react-router

Usage

Step 1

In your root reducer file,

  • Create a function that takes history as an argument and returns a root reducer.
  • Add router reducer into root reducer by passing history to connectRouter.
  • Note: The key MUST be router.
// reducers.js
import { combineReducers } from 'redux'
import { connectRouter } from 'connected-react-router'

const createRootReducer = (history) => combineReducers({
  router: connectRouter(history),
  ... // rest of your reducers
})
export default createRootReducer

Step 2

When creating a Redux store,

  • Create a history object.
  • Provide the created history to the root reducer creator.
  • Use routerMiddleware(history) if you want to dispatch history actions (e.g. to change URL with push('/path/to/somewhere')).
// configureStore.js
...
import { createBrowserHistory } from 'history'
import { applyMiddleware, compose, createStore } from 'redux'
import { routerMiddleware } from 'connected-react-router'
import createRootReducer from './reducers'
...
export const history = createBrowserHistory()

export default function configureStore(preloadedState) {
  const store = createStore(
    createRootReducer(history), // root reducer with router state
    preloadedState,
    compose(
      applyMiddleware(
        routerMiddleware(history), // for dispatching history actions
        // ... other middlewares ...
      ),
    ),
  )

  return store
}

Step 3

  • Wrap your react-router v4/v5 routing with ConnectedRouter and pass the history object as a prop. Remember to delete any usage of BrowserRouter or NativeRouter as leaving this in will cause problems synchronising the state.
  • Place ConnectedRouter as a child of react-redux's Provider.
  • N.B. If doing server-side rendering, you should still use the StaticRouter from react-router on the server.
// index.js
...
import { Provider } from 'react-redux'
import { Route, Switch } from 'react-router' // react-router v4/v5
import { ConnectedRouter } from 'connected-react-router'
import configureStore, { history } from './configureStore'
...
const store = configureStore(/* provide initial state if any */)

ReactDOM.render(
  <Provider store={store}>
    <ConnectedRouter history={history}> { /* place ConnectedRouter under Provider */ }
      <> { /* your usual react-router v4/v5 routing */ }
        <Switch>
          <Route exact path="/" render={() => (<div>Match</div>)} />
          <Route render={() => (<div>Miss</div>)} />
        </Switch>
      </>
    </ConnectedRouter>
  </Provider>,
  document.getElementById('react-root')
)

Note: the history object provided to router reducer, routerMiddleware, and ConnectedRouter component must be the same history object.

Now, it's ready to work!

Examples

See the examples folder

FAQ

Build

npm run build

Generated files will be in the lib folder.

Development

When testing the example apps with npm link or yarn link, you should explicitly provide the same Context to both Provider and ConnectedRouter to make sure that the ConnectedRouter doesn't pick up a different ReactReduxContext from a different node_modules folder.

In index.js.

...
import { Provider, ReactReduxContext } from 'react-redux'
...
      <Provider store={store} context={ReactReduxContext}>
        <App history={history} context={ReactReduxContext} />
      </Provider>
...

In App.js,

...
const App = ({ history, context }) => {
  return (
    <ConnectedRouter history={history} context={context}>
      { routes }
    </ConnectedRouter>
  )
}
...

Contributors

See Contributors and Acknowledge.

License

MIT License

NPM DownloadsLast 30 Days