Demystify connect in react-redux (Part 1, closures & higher order components)

Pandula Weerasooriya
9 min readMay 23, 2020

--

The natural journey of a React developer is to build a few toy applications using idiomatic React with stateful class components and a few functional components. And then he or she moves on in to a more centralized state management system like Redux or React context.

Right now, I’m in the phase of building an application in my work placement with React and I first hand understood the importance of managing the application state at one place. So, I started studying Redux. Which wasn’t easy because of the novelty of the design patterns that Redux imposed such as flux and pub-sub. However, I managed to gain some confidence in the Redux arena and watched few tutorials on react-redux. Then I saw the connect function. Which, somehow takes our component and give it access to the Redux state. But, what intrigued me the most was the way that it was called, like connect(mapStateToProps, mapDispatchToProps)(component).

This obviously looked like a very weird way of calling a function and therefore I determined to understand the underlying architecture of the function. However, in my journey I’ve found that it involves a few advanced React patterns and some knowledge in JavaScript closures to fully appreciate it. Therefore I thought of writing an article series which slowly builds up to building the connect function from scratch. So, in this first article, we’ll take a look at JavaScript closures and then React higher order component (HOC) pattern which utilize closures.

JavaScript closures

Closures are often regarded as a daunting topic that is harder to understand. Which, I think is due to the way that they are often being taught in tutorials and books. Closures are explained through dummy examples such as below and actual use case scenarios are never explained.

So, we’ll also try to understand closures from the above dummy example and later on we’ll look at how they are used in practice with HOC.

In a nutshell, closures are a feature in JavaScript, where when a function is defined inside another function, the inner function stores the variables of the outer function in its scope.

Before reading the definition again a second time, let’s look at what happens when we execute the outer function. When, we call the outer function, it returns the inner function and get popped from the call stack. Which means, that variables that were defined in its scope will be lost. If you try console log the variable b it will give a reference error as expected.

Okay, so all good at this point. However, now let’s save the returned inner function in a variable.

Voila!, calling the inner function has returned us a the expected outcome. But, the b variable is not defined in the global scope and it’s obviously was not defined in the inner function’s scope. Therefore, the important thing to understand is that the inner function has access to another scope, called closure scope. Which saves the state of it’s outer function, even after its popped off from the execution stack. And, this very behavior of JavaScript has given us so many applications and has enabled us to use functional programming patterns like currying. Throughout this article series, we’ll look at few real world examples where closures are being used.

Let’s look at a slightly more advanced example to hammer home this concept clearly.

The above, returns a function called b, which in turn returns another function called c. Let’s take this step by step. When we first call function a, it’s going to return function b and get popped off from the call stack. And I can save that the intermediary function (b) to another variable, or call it again straight after calling a (meaning that, we would actually be calling the function b) and save the final, function c to a variable.

We can see that the function c has returned the expected output. What has happened here is that, when the function c is called, it will have access to the variable object from it’s own scope. However, it won’t have access to the variables, name and verb. So, it will go up the scope chain to find the said variables. In this case, the function c will get access to the variable verb by its closure scope which was defined by its outer function, b. However, function b doesn’t have the variable name defined in its scope. Therefore, function c will go another step upwards in the scope chain and it will find the variable name, defined in the closure scope of function b.

One of the best explanations of closures, scope chain and execution stack is given in this video.

https://www.youtube.com/watch?v=Nt-qa_LlUH0

Please go through it to understand closures more clearly. However, this is enough for us right now to dive in on to the HOC pattern in React.

Higher Order Component pattern in React

Now that we have gotten our feet wet with closures, lets look at a pattern where they can be used in React. According to the React Doc,

A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React’s compositional nature.

The important thing to understand here is that, HOCs are not exactly a feature of React and they are used mainly to reduce code repeatability and compose similar features in a higher order component above our base component.

Let’s try to understand this by looking at a simple example. I have created a simple ToDo component and a Goal component who’s only functionality is to create an item and push it to the DOM.

Todo Component
Goals component

I kept the code pretty simple for both components. Each of them has two state objects where one state object handles the input element and the other state object pushes input value to an array, which we use to display in a list. It is apparent that both components share similar sort of logic and similar sort of states. So, our goal in this chapter is to figure out a way to compose this state and behavior(click handlers) in to a single component

So, let’s start with baby steps.

You can see that I have a created a new file called WithItemState, which returns a function. The important thing here to notice is the structure of this function. It takes in a React Component as an argument and returns another component which wraps that passed Component. Take your time to read this function few times and understand it structure.

In our Todo component, I have imported our WithItemState function and when we export our component, I have simply called the higher order function with our component.

Let’s understand what will happen here. When the program starts, the WithItemState(Todo) will be called immediately, and it will spit out our Todo component, now wrapped in another Component. Basic functionalities of the Todo component will exactly be the same and if you were following along with me, you would see that nothing has changed in the output. And I did a similar thing in Goals component as well. Okay, so now I’m sure that you must be questioning the very reason to do this, as we just basically made our program way more complicated than it has to be.

So, I made the necessary changes to our higher order component. You can see that, I created a generic state to handle any input, whether it may be todos or goals or anything else. And I have also created some event handlers and I have passed them all to the inner component as props. You can think of it as machine where when you put a cake into it, it will spit out that cake with icing and a cherry on the top. But, nothing would happen to the underlying cake.

Right, so now that we have added all these props to component passed in to our higher order function, let’s see how to use these in our Todo component.

Our code has become way more cleaner right? So, essentially we turned our stateful component into a stateless dumb component. The similar thing can be done for the goals component as well. So, this is what higher order components are all about. They take in a component and return a wrapped component which handles state and take care of the UI or business logic.

Now that you have seen HOCs, where does closures come into place? As I have mentioned before, when the program starts the higher order function gets called immediate and pops of from the stack and if JavaScript hadn’t had closures, it wouldn't have been able to use the passed component, since it was not in its scope. Of course, you didn’t have to know that to use HOCs, but having an understanding of the underlying basics always comes in handy at tight situations.

There’s one more important thing that you should know about HOCs. Which is, how to pass its own props down to the inner component. Let’s see this in action.

You can see that, in our App component I have just imported and mounted both Todo and Goals component. However, I have also passed down a title props to those components. What you have to understand in here is that, the props that will get passed down to our components are actually passed down to the wrapped higher order component and not to our inner component itself. So, in order to pass this down to the inner component, we have to do something like this,

HOC returning the inner component

We have basically passed down the title prop received by the higher order component down to our inner component. Where, inner component can use it as a just another prop. However, this solution is not scalable as, its hard to predict the number of props that will get passed down, as these days we wrap everything with things like Redux, Context or Any UI framework like Material UI. So, the best solution is to actually spread the props HOC received as below.

In this case, we don’t have to keep track of props in HOC and our component as everything get passed down as it is.

Right, so this article comes to an end here. I know that it isn’t easy to wrap our heads around all these functional programming ways, but once you do get the understanding, the satisfaction can be immense :)

I have not talked about Redux or the Connect function here at all here, and we will come to that at the very end where everything will fit in together nicely. The next article will be on React Context and another advanced design pattern of React called render props. Stay tuned!

--

--

Pandula Weerasooriya
Pandula Weerasooriya

Written by Pandula Weerasooriya

A fullstack engineer who's passionate about building data intensive products and distributed systems. My stack includes Golang, Rust, React, NodeJS and Python.

No responses yet