Why you should stop using the “container/presentational” pattern in Redux

Matan Borenkraout
Aug 3 · 4 min read

TL;DR:
The redux style guide has an important rule: “Connect More Components to Read Data from the Store”. This rule has some important performance aspects that are covered with an example in this post.

Photo by frank mckenna on Unsplash

The “Container/Presentational” Pattern used to be the best practice when using redux or any other store management package.
It was explained thoroughly by Dan Abramov and Michael Chan.
If we want to keep it short, a container usually holds the data fetching logic and data access to store. On the other hand, a presentational component is more generic and just present the data it gets as props.
This pattern was common before React Hooks were introduced and probably every developer using React with classes has seen or used it.

But in the world of hooks, this approach can cause serious performance issues (we will cover those later on).
Moreover, the Redux best practices now suggests we should connect more components to read directly from the store (which is quite the opposite to this pattern).

“Prefer having more UI components subscribed to the Redux store and reading data at a more granular level. This typically leads to better UI performance, as fewer components will need to render when a given piece of state changes.” (The redux docs)

But, what’s the reason behind this rule?

Our example app

In the first approach, I decided to use connect on a container, query all the data from the store and also mapDispatchToProps so I’ll be able to dispatch some data fetching.
I passed the data to my components using props (the example uses styled-components but the actual styles were left behind):

My components just fetch the data and show it based on the props.
I opened the React profiler, recorded a click on a Pokemon name and saw the renders that it triggered.
Here’s the screenshot:

What do we see here?
When clicking on a Pokemon name on the left sidebar, we initiated two renders. In the first one we see the PokemonsSidebar was rendered and it took 1ms. But, why was it even rendered? It didn’t change, nor did it’s props. The reason for that is that the parent component was rendered because of a change in the redux store, so all of it’s children should also render.
We can also see that the whole Render duration was 13.6ms, that’s because inside the PokemonsSidebar we have 150 li‘s that rendered again for no reason because their parent re-rendered.

In the second approach, I refactored my code to useSelector and useDispatch. My presentational components will be connected directly to the store and dispatch the actions.
Here’s my component’s code:

Let’s see the profiler screenshot:

As we can see here, the PokemonsSidebar didn’t re-render because it wasn’t subscribed to the selectedPokemon data from the store, thus all of it’s children didn’t re-render. The Render duration this time is only 0.9ms (compared to 13.6ms)!

These numbers may sound negligible but that’s just an example. My app isn’t complicated and there’s just one component that shouldn’t render (and it’s children). What if I had more components? and my components had a heavy render?

Why does it happen?

Disclaimer

Summary

I hope everyone’s feeling well and keeping themselves safe!
If you have any questions, I’m here and also on Twitter. Feel free to ask or comment, I’d love to hear your feedback!

Thanks,
Matan.

Read More:

Nielsen-Tel-Aviv-tech-blog

A publication by the Nielsen Tel Aviv Engineering team…

Nielsen-Tel-Aviv-tech-blog

A publication by the Nielsen Tel Aviv Engineering team, where we talk about what we do and how we do things

Matan Borenkraout

Written by

Frontend Engineer | Creating better software, one word at a time | Matan.io

Nielsen-Tel-Aviv-tech-blog

A publication by the Nielsen Tel Aviv Engineering team, where we talk about what we do and how we do things