Ganesh Mani I'm a full-stack developer, Android application/game developer, and tech enthusiast who loves to work with current technologies in web, mobile, the IoT, machine learning, and data science.

Why you don’t need to mix routing state with Redux

3 min read 1067

The Redux and React logos.

This article covers some of the reasons why you don’t need to mix routing state with Redux.

Before we start with the reasons you don’t need to mix the routing state, let’s understand how routing state with Redux works.

There are different libraries and methods available to integrate the routing state with Redux. A few of them are react-router-redux and redux-first-router. This article covers how the Redux-first router works.

How Redux Routing Works

A flow chart demonstrating how redux routing works.

There are two ways that the user can route through the application. One is internally, where user clicks a link in our application, for example: Navbar.

Another option is externally, where a user enters the url in the browser.

Internal navigation

When a user clicks a link in our application, an action is dispatched with navigation data. Our Redux middleware picks up the action and updates the browser history along with the reducer, which updates the Redux state.

After that, our connected route listens for the change of state and determines how the page renders based on the Redux state.

External Navigation

When the url is changed in the browser. our listener in the Redux store observes the change and dispatches an action to update the state and history.

A good example would be when you hit a home url directly in the browser.

We made a custom demo for .
No really. Click here to check it out.

Implementation

Let’s see a simple example, which uses the Redux-first routing approach. This will help you to understand how it is implemented in our application.

configureStore.js

// configureStore.js
import { applyMiddleware, combineReducers, compose, createStore } from 'redux'
import { connectRoutes } from 'redux-first-router'

import page from './pageReducer'

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

export default function configureStore(preloadedState) {
  const { reducer, middleware, enhancer } = connectRoutes(routesMap)

  const rootReducer = combineReducers({ page, location: reducer })
  const middlewares = applyMiddleware(middleware)
  const enhancers = compose(enhancer, middlewares)

  const store = createStore(rootReducer, preloadedState, enhancers)

  return { store }
}

Here, we have connectRoutes, which maps the router with components to render. After that, we use the route reducer, along with other reducers inside the combine reducer.

Then, we have middlewares, enhancers, and rootReducer to createStore.

pageReducer.js

 // pageReducer.js
import { NOT_FOUND } from 'redux-first-router'

const components = {
  HOME: 'Home',
  USER: 'User',
  [NOT_FOUND]: 'NotFound'
}

export default (state = 'HOME', action = {}) => {
  return components[action.type] || state
}

Here, the reducer function contains the components that need to be rendered based on the route. For example, if the action type is HOME, then our reducer will return the state based on that type.

App.js

// App.js
import React from 'react'
import { connect } from 'react-redux'

// Contains 'Home', 'User' and 'NotFound'
import * as components from './components';

const App = ({ page }) => {
  const Component = components[page]
  return <Component />
}

const mapStateToProps = ({ page }) => ({ page })

export default connect(mapStateToProps)(App)

components.js

// components.js
import React from 'react'
import { connect } from 'react-redux'

const Home = () => <h3>Home</h3>

const User = ({ userId }) => <h3>{`User ${userId}`}</h3>
const mapStateToProps = ({ location }) => ({
  userId: location.payload.id
})
const ConnectedUser = connect(mapStateToProps)(User)

const NotFound = () => <h3>404</h3>

export { Home, ConnectedUser as User, NotFound }

In App.js, we have the page state from Redux, which determines the component to load based on the navigation state.

Meanwhile, components.js contains different components to load in our React application.

Why you don’t need Redux for routing

Having routing state in Redux may be a good option in some scenarios. However, there are lot of problems that come along with it.

Complexity

One of the major problems that you will face while having routing state in Redux is complexity.

You can’t predict how complicated it will be. Your complete application state will rely on Redux.

For a few of us, this complexity can be a good thing. But you have to manage everything in one place, which can be difficult to do when your application starts to grow. In my opinion, it is unnecessary.

It would be like managing all your components’ state in one place. Think about how hard that will be when your codebase grows.

Verbosity

Another problem that you might need to handle is that you’ll end up with a lot of code for solving simple problems. You might need to write a lot of code just to navigate to a page, when this could be avoided easily.

You have to manage all the actions and reducers just for routing, along with the middleware to update the browser history API for routing.

Code redundancy

You could end up writing lots of redundant code if you use Redux for routing, which could be avoided easily. For example, you might need to write a lot of actions and reducer functions to handle the route functionality.

This may give you some power to control the router logics on your own, but you may not need that power to handle most of the application requirements.

So, you might end up writing the code that could be simplified if you used client-side routing.

Alternatives to Redux Routing

One of the popular ways for routing problems in the React ecosystem is react-router. It is a client-side router that solves most of the problems we face when developing React applications.

Some of the advantages of React routers are:

Dynamic route matching

Using react-router, we can match the dynamic routes with React components. Consider that you have an application requirement for a dynamic subdomain:

logrocket.slack.com

Here, the subdomain changes dynamically. We can handle that route using react-router easily. We can also perform some actions based on the subdomain using react-router without a need to go to Redux.

Browser History Features

Browser history features such as navigating back and forth on our application route come out-of-the-box in react-router.

Lazy Code Loading

react-router supports lazy code loading. This helps you split your code bundle based on priority. You can load the primary feature in the top bundle, and load the second features in the split bundles.

Summary

At the end of the day, all that matters is the problem that we solve using the tech tool. Importantly, we need to do that in a simple and efficient way. Of course, there will be some benefit to using the Redux-first routing approach.

But we can solve the same problem using simpler means that we discussed in this article. There are lot of libraries that help us to do that, such as react-router.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Ganesh Mani I'm a full-stack developer, Android application/game developer, and tech enthusiast who loves to work with current technologies in web, mobile, the IoT, machine learning, and data science.

2 Replies to “Why you don’t need to mix routing state with…”

  1. I can’t agree less.
    Redux is all about managing the entire state in a scalable way. Its useful to have the current page and parameters in the store instead of in an additional place accessed and modified in a different way.

    Its actually less complex.
    It is dynamic, you imply it isn’t.
    Browser history is supported by redux easily therefore the state of the navigation as well.

  2. Absolutely true. I think the biggest problem with all these articles saying redux is bad for X or Y simply didnt understand how to work with redux. Its super simple and VERY powerful. I just don’t get people who say anything else.

Leave a Reply