React Redux Boilerplate with Authentication, Authorization and Architecture Best Practices

By Ryan Vice | Posted on March 22, 2018

React| Testing

Overview

We’ve created a boilerplate based on years and many projects in React Redux that can help get you started with:

  • Routing
  • Authorization
  • Authentication
  • Code Organization

It’s based on create-react-app and also demonstrates our High ROI Testing approach.

The Big Two

There are two things that we recommend doing that we call our big two. React Redux has some great performance optimizations but if you aren’t careful it’s easy to get into bad situations like the ones described in Common Problems in Naive Redux Implementations. However, below are two simple things you can do that will help you avoid these situations.

Only Update State in Selectors

We discuss the selector patter in our boiler plate here and we can’t stress enough how important it is to follow this approach. If you only access state in selectors then you will effectively define an API for access your state atom and this will allow you to easily change the details of your state atom shape over time. You will want to evolve your state atom design and as your code becomes complex you will want to consider patterns like state normalization and reducer composition. Having selectors between your components and state will make this trivial to do.

Install redux-immutable-state-invariant in Dev Builds On Day One

While you should always follow Redux’s Immutable Update Patterns it is strongly recommended that you give yourself a safety net and we like the redux-immutable-state-invariant middleware. It’s the simplest way to keep your state atom following immutable update approaches because all it does is throw an exception if you mutate state. We recommend configuring it in your non-production builds and you should be able to easily find and fix state mutation problems. There are other tools out there like immutable.js but we recommend against using these tools for two reasons (1) it increases ramp up as you have to learn new syntax for doing something as simple as updating an array element (2) it will delay the pain points in your state atom design that will have you looking to improve it with patterns like state normalization and reducer composition.

Common Problems in Naive Redux Implementations

We’ve seen it on projects big and small. Once your app starts getting big you can find that you start having the types of problems below.

Views not updating

This happens because Redux assumes your model is immutable and has performance optimizations based on this assumptions. For example, connect() will prevent your component from rerendering if the results of it calling mapStateToProps() has changed and more importantly it uses a shallow compare to figure out if the results have changed. This means that if you are returning { foo: state.foo} and then in your render() method you are doing this <p>this.props.foo.bar</p> then if some other component or code mutates like this state.foo.bar = 'something new' then your component won’t rerender as state.foo hasn’t changed (it’s still holding the same pointer). You can find the redux mutation best practices here.

Having to do deep dirty compares

One way to get out of the situation described in Views not updating above is to deep clone your state when it comes out of reducers. This will enforce that your state has changed and allow your views to update. I’ve seen this having to be resorted to on a large project because by the time the views stopped updating there was so much code and it would have been to hard and expensive to fix all the state mutations. However once we did this then we had to use _.isEqual() from lodash to do deep quality compares in our componentWillReceiveProps methods which caused huge performance loses.

Large cost for changing your state atom shape

Another thing that can happen over time is that your components will be doing things like this

mapStateToProps(state) {
   bar: state.foo.bar
}

Which seems harmless enough but the problem is that it couples your component with the state atoms shape and over time has things get really complex it can make refactoring your state atom cost prohibitive which can lead to overly complex and redundant state atom design.

Repository

https://github.com/RyanAtViceSoftware/vice-react-boilerplate

Video

This video talks through a lot of the concepts in the boilerplate

Watch Video Series

5 Keys to Success Before Building Your Software

You may have considered getting a custom software system to help your business run more smoothly, but how do you get started? We will look at 5 factors that we feel are critical to success when building a custom software system.

Need an expert team of designers, mobile developers, web developers and back-end developers?

Discover Vice Software