Top Related Projects
Declarative routing for React
🧭 Declarative, asynchronous routing for React.
🥢 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
- 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)
)
)
)
- 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')
)
- Dispatching navigation actions:
import { push } from 'connected-react-router'
// In a component or action creator
dispatch(push('/home'))
Getting Started
-
Install the package:
npm install connected-react-router
-
Create a history object:
import { createBrowserHistory } from 'history' const history = createBrowserHistory()
-
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 })
-
Use
ConnectedRouter
instead ofBrowserRouter
: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.
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.
🧭 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.
🥢 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 designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
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
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 passinghistory
toconnectRouter
. - 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 withpush('/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 thehistory
object as a prop. Remember to delete any usage ofBrowserRouter
orNativeRouter
as leaving this in will cause problems synchronising the state. - Place
ConnectedRouter
as a child ofreact-redux
'sProvider
. - N.B. If doing server-side rendering, you should still use the
StaticRouter
fromreact-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
- How to navigate with Redux action
- How to get the current browser location (URL)
- How to set Router props e.g. basename, initialEntries, etc.
- How to hot reload functional components
- How to hot reload reducers
- How to support Immutable.js
- How to implement server-side rendering (sample codebase)
- How to migrate from v4 to v5
- How to use connected-react-router with react native
- How to use your own context with react-redux
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
Top Related Projects
Declarative routing for React
🧭 Declarative, asynchronous routing for React.
🥢 A minimalist-friendly ~2.1KB routing for React and Preact
🎖 seamless redux-first routing -- just dispatch actions
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot