3 simple steps to improve your React Redux code
Technical Opinion

3 simple steps to improve your React Redux code

Let’s face it: developing scalable front-end code isn’t piece of cake. No matter how well-structured the framework/architecture you’re using is, everything will be converted to ye olde HTML, CSS and (vanilla) JS.

Well, the good news is the open-source community already created solid frameworks (like AngularJS and ReactJS) to make your life incredibly easier, so you can work on high-level code and nevermind the hardcore stuff.

This brings up a new scenario, though – after getting used to building things the old-fashioned way (or not-so-old-fashioned, with tools like Backbone.js or Ember.js), you’ve decided to try what is trending on front-end development now: ReactJS, using the Redux architecture. You got excited with the possibilities this opens (and – oh my! – the ability to ditch jQuery once and for all), and, after working for a few weeks you realize that your code is a total mess.

Don’t be alarmed – you can fix that. I’ll share a few insights on how I transformed my Frankenstein into a clean and Redux-compliant codebase, while still being able to deliver new features.

The insights from this article might also be useful for seasoned developers, who want some tips on how to achieve a better-organized and scalable code.

1. Define the role of your components

When starting with React+Redux, people tend to build massive components, which contain a whole bunch of logic and connect to many Store states. It is not uncommon to find people treating components as HTML templates — you have one for each page, and you simply translate the HTML code into JSX in the render() function.

Developing things in such way invalidates one important advantage of this pattern, which is the ability to reuse components throughout your web application, and propagate state changes when they affect more than one component or page.

components

There are two types of components in the React/Redux architecture: presentational and container components.

  • Presentational Components (often referred to as ‘dumb components’) are all-normal ReactJS components, which do not contain any logic or store connection – they are simply ‘views’ to display data. These components usually receive some props and display them or trigger actions depending on the user behavior (the actions should be sent as props to the components, as no business logic is defined on presentational components).
  • Container Components (often referred to as ‘smart components’), on the other hand, don’t do anything visual: they are the ones who’ll process and pass data to the presentational components. Containers will be the components that connect to the Store and import actions, so you’ll often see mapDispatchToProps() and mapStateToProps() definitions inside them.

In most cases, developers tend to structure the entire application as a set of container components. In order to fix this, two steps have to be taken:

1.1. Break your containers into presentational components and container components

 

This will enable you to create several pieces of reusable code, so that your front-end will have a consistent look, and you’ll force yourself to avoid duplicated code to address similar problems.

Taking this blog’s index as a reference:

Artboard 2

We could split it into the following components and containers:

Sliced Blog Index

Suggestion of componentization of this blog’s index. Notice that this is for illustration purposes, as it’s up to the developer to define the granularity of each visual component.

You can observe that it is possible (and fairly common) to put a container inside a container, in order to modularize and structure the code.

1.2. Center the communication in the containers

 

Your container components are the ones responsible for knowing which actions should be triggered and what state updates they need to receive.

Think of containers as structural components: they are fundamental for your code, but they don’t mean anything visually — they just define what data will be presented by the presentational components, and how they should behave.

2. Decide what state information actually needs to be in the Store

The idea of having a globally accessible Store with all the variables from the system might sound promising, but listen to me: it’s a trap!

Store states should be used with caution, and not for anything that is used as a presentation variable. In other words, it makes sense to store the username and avatar link globally, but the enabled/disabled status of a button in a form might as well live as a local state of the container component.

There is no 100% accurate rule to define when to use the Store or not, but you should take into account the implications when you decide to go down that road. The Store does not clear data automatically when your router changes context, which might cause unexpected behavior when you go back to a context where you’ve already taken actions.

To make this less abstract, let’s think of a search engine where you store the number of the result page and the search term in the Store. You perform a search, go to the third page of results, then click on the ‘home’ button (usually the logo) to return to the root search page. Guess what? Your search term is pre-populated in the input box. You delete it, enter a new search term and click on ‘search’. Suprise, again:  you’re already on the third page of the search results. Weird, right?

This is because the application state (Store) will persist as long as you keep the web application open, without caring about expiry time or user behavior. Unless you explicitly clear the data used in a given context, it will remain there and show up when you less expect. I’m not saying this is always undesirable, but those edge cases must be well-thought when defining what should be put in the Store.

3. Consider sharing your CSS components’ namespaces

Many people think of React/Redux as a new mindset for JavaScript and HTML, and think of CSS as something completely apart – continuing to develop it the old-fashioned way, i.e., everything in a single CSS (or SCSS, at most) file.

Whether you should use a React-Friendly JavaScript CSS library to write inline CSS, or simply use well-defined CSS Architecture is entirely up to you – just keep in mind that the naming of each component should be consistent on both JS and CSS. This way, you’ll be able to easily find where the styling of a specific component is defined, and will avoid merge conflicts when many developers are working in the same codebase.

Wrapping up

Improving your code is a continuous effort – and realizing it needs to be done is a sign that you’re constantly evolving your skills and mindset. It is usually a good idea to refactor your code gradually, while still delivering new features. I hope this post helps you improve your React code – please share your opinion in the comments below.

Edit: removed the GIFs as many readers suggested – thanks for the input, guys! :)

About the author

Alex Cordeiro

Progressive rock lover, programming languages aficionado, full-stack web/mobile developer and pentesting enthusiast. Legend says he's never lost a Pokémon battle.

Need a team for your projects?
We'd love to hear your ideas!

Connect with us!
  • Pedro Kurtz

    This post’s author is a liar. He’s lost countless Pokémon battles. To me.

    Great article!

  • Lucas Constantino Silva

    Great article. Consider having a look at CSS Modules: they solve the 3th step with no architecture at all and no inline style hell 😉

  • Hey! Nice post, glad to see more people suggesting Redux with React!

    How’s your Redux’s files structure? like reducers, actions and middlewares? I’m using https://github.com/choko-org/redux-boot which helps to create Redux modules.

  • Adam Terlson

    Hey mate, enjoyed the article! It seems though that in your container vs “dumb” component diagram, you have multiple “dumb” components in a single container. Without trying to read too much into a simple diagram, do you think it’s a better idea to have many independent, more focused containers which connect state “as low as possible” in the component tree, or to have a top-level orchestrator which also knows about state?

  • Jason Cochran

    awesome post! My project manager and I were discussing splitting up components and containers and css management earlier today. This helps drive home that point. Thanks!

  • Michael Snead

    I’d like to present a different opinion on #2. In the case of the search example, the generation of the “initial state” (search text is empty, page starts at 1, etc) could be generated by a function. Call the function once to “setup” the page when you first render. Call it again when you want to “reset” the entire search page. If you can’t get the entire state, or derive the entire state from what’s inside your store, you miss out on some of the benefits of using Redux.

  • Bill Schneider

    Another point on #2 – state in the Store also requires an additional layer of indirection. Instead of just setting state, you dispatch an action, which is handled by a reducer, which generates a new state. So it’s harder to figure out what the code is doing just by looking at it, with more layers to trace through.

    I would think of the Store like session scope in a server-side app — use it for when state cannot be cleanly managed by a single container component, or when the state needs to persist across routes or page reloads. “Do whatever is less awkward.” (https://github.com/reactjs/redux/issues/1287)