The Power of Redux and React.lazy: Reusing UI and the Data Layer

Image for post
Image for post
Intersection de deux parallèles — Picture under Creative Commons License (source:


This article proposes a solution for dynamically changing Redux containers on the fly to reuse, not only the UI components, but the Data-layer too, by switching the mapped action-creators on runtime, using two main concepts, lazy-loading (with React.lazy) and Duck Typing. If you don’t have much time to go through the step-by-step, check the resume at the end of this article.

Note I: Before copying the gists from this article, I created a repo that does the exact same thing: react-redux-lazy. Go there and check it out 😉
Note II: For the sake of simplicity, I’m using thunks, but it should work with sagas and epics too. What is important are the action-creators contract.


Last year, before the introduction of the React.lazy and Suspense APIs, I wrote an article showing how to implement by yourself the very same feature. Also, last year, I wrote an article showing the power of Duck Typing in JavaScript and in React. Now going further, let’s add this logic to a Redux application, and check how to combine both patterns to reuse your data and UI layers of the application, just by switching the provider of the actions at runtime.

The Scenario

Imagine an app that you can manage blog posts, where the user first, login, then the app lists all the posts on the history, and finally, you can create new ones, edit or delete. Yep, the good’ol CRUD.

But knowing that the user wants your app to support as many blogs services it can, but with the basic features of any blog platform. How can you do that in a way that you can reuse your data-layer + UI? Basically you want to load posts, edit them (or create new ones) and send to the server, right?

But hey, you don’t want to bloat your app with dozen of business logic and SDKs for all the supported platforms at once! Just load the code for that platform if the user choose that platform.

The Solution

Although we’re approaching this CRUD app, this solution can be applied to many scenarios that you have a certain generic scope, where the actions and the data are similar.

If you think in an app that uses React and Redux, being simplistic, you can divide it in this 3 parts:

  • React Components -> User interface

And there’s one entity responsible to tie this together, they are the Containers. They’re non visual Components that makes a bridge between the store, more specifically action-creators (wrapped to dispatch) and the App State, to your UI components.

As you can see, is there where we’re going to introduce the lazy loading, using the strategy pattern to load the proper business rules on the fly.

But hey, how the UI Components and the Reducers are going to accept different action creators? This is the trick, you’ll use Duck Typing, and build up action creators that dispatch the same action in the end, but internally they’re doing that through a different way (of course, each platform have it’s own SDKs and specificities)

For instance, thinking in our blog manager example, we’re going to have the PostEditor component. Let’s suppose this component will need the following actions:

  • publishPost(postText)

For each and every platform, we’re exposing this very same actions-creators, internally using their own flows, but always dispatching the same actions, with same “type” and “payload” data format. This is important for the reducers, as they’re expecting data on a defined format (a contract) from the actions.

Let’s see what we want to achieve:

Image for post
Image for post

The state tree is going to be the same, so we can define the mapStateToProps as normally is done. The dynamic thing here are the action-creators, so the mapDispatchToProps are going to be async.

But as you may know, the connect from “react-redux” accept objects for the mapDispatchToProps, so we’ll need to create a “lazy” version of the connect.

From connect to an async connect:

See the trick here, React.lazy expects a “export default” component, and we give that to it :)

With our lazyConnect implemented, let’s check how we can use it:

So, the LazyPostEditor is the dynamically connected version of PostEditor, and will pass forward all props passed to it.

Of course, you can let the responsibility to wrap on <Suspense/> for the component which will use it, and also, don’t have any visual elements on the container (like the loading indicator), you can achieve this by returning directly the “lazyConnect” result. But to maintain this example simple, let’s keep it like this. So, you can simply use this as a common component:

<LazyPostEditor platform="blogo-blog"/>

This will make the actions inside “actions/blogo-blog/post.js” be bound to the PostEditor component through the props, and every time this component calls one action, is going to be for the right platform.

But let’s see how are the actions of “blogo-blog” and another fictional platform, “blog-fu”:

“Blogo-blog” thunks:

“Blog-Fu” thunks:

As you can see, both expose the “same” methods. Although you can expose these functions with different names/nicknames (yes you can put different names on them as long you map them properly to the Component using the mapDispatchToProps) you need to follow the same argument signature, as you’re expecting a call pattern coming from the component (remember, Duck Typing!).

Other important aspect is the data format on the action payload. As you can see, both SDKs deliver them in a different format, but as the reducers are expecting it in a protocoled format, you’ll need to parse it. The downside on this is that you may end losing information, as all platforms have their specificities, but hey, this is a common side-effect of adding an abstraction layer to make something specific, generic.

Ok, let’s wrap up.


  • Define a generic state tree (+reducers, +actions) with your solution in mind. In this article, the example is for blogs, in your case can be like loading users from different providers, or locations of restaurants, doesn’t matter, just make sure to create a solid entity that can attend the core information that exists on all data sources;


Reusing the UI + Data Layer for a generic solution will make you lose specific data/behaviour, but this is a common side effect of any abstraction layer you add to your application, so if you really need a generic solution this will not be a big contra. In the other side, the pros of such approach will make your app easy to extend. Is like a plug and play solution for data: add more platforms by simply following the protocol of the actions and the path/filename and you’re pretty much done (check open-closed pattern from SOLID).

Other important aspect are the tests. As you’re using a strategy pattern to select the action creators, you can add a fictional platform on your test runs without the need of proxying the imports or dependency injection, you’ll just get this “feature” out of the box!

Such abstractions as the lazy/Suspense, added to React, are just a ladder for us, developers, to think outside the box and create awesome solutions from that.

Frontend Weekly

It's really hard to keep up with all the front-end…

Rubens Pinheiro Gonçalves Cavalcante

Written by

Front End Engineer at OLX Group

Frontend Weekly

It's really hard to keep up with all the front-end development news out there. Let us help you. We hand-pick interesting articles related to front-end development. You can also subscribe to our weekly newsletter at

Rubens Pinheiro Gonçalves Cavalcante

Written by

Front End Engineer at OLX Group

Frontend Weekly

It's really hard to keep up with all the front-end development news out there. Let us help you. We hand-pick interesting articles related to front-end development. You can also subscribe to our weekly newsletter at

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store