State Management with React Hooks — No Redux or Context API

React Hooks are more powerful than you think.

André Gardi
Apr 8, 2019 · 5 min read

Today, we are going to explore it and develop a custom Hook to manage global states — an easier to use method than Redux, and more performant than Context API.

Image for post
Image for post

The basics of Hooks

If you are already familiar with React Hooks, you can skip this part.

useState()

Before Hooks, functional components had no state. Now, with the , we can do it.

Image for post
Image for post

It works by returning an array. The first item of the above array is a variable that gives access to the state value. The second item is a function that updates the state of the component to reflect the new values on the DOM.

useEffect()

Class components manage side effects using life cycle methods, like . The function lets you perform side effects in function components.

By default, effects run after every completed render. But, you can choose to fire it only when certain values have changed, passing an array of variables as a second optional parameter.

To have the same result as we can send an empty array. Knowing that an empty set does never change, the effect will run only once.


Sharing states

We can see that Hooks states works exactly like class component states. Every instance of the component has its own state.

To work a solution which shares state between components, we will create a custom Hook.

Image for post
Image for post

The idea is to create an array of listeners and only one state object. Every time that one component changes the state, all subscribed components get their functions fired and get updated.

We can do that by calling inside our custom Hook. But, instead returning the function, we add it to an array of listeners and return a function which updates the state object and run all listeners functions.

Wait. Isn’t this supposed to make my life easier?

Yes. I created a NPM package which encapsulates all this logic.

You will not need to this rewrite this custom hook on every project. If you just want to skip ahead and use the final solution, you can easily add it in your project by running:

npm install -s use-global-hook

You can learn how to use it by the examples in the package documentation. But, from now on, we are going to focus in how it works under the hood.

The first version

To use it on a component:

This first version already works sharing state. You can add as many Counter components as you want in your application and it will all have the same global state.

But we can do better

What I didn’t like in this first version:

  • I want to remove the listener from the array when the component is unmounted.
  • I want to make it more generic, so we can use in other projects.
  • I want set a by parameters.
  • I want to use more functional oriented programming.

Calling a function just before component unmount

We learned that calling the , with an empty array, has the same use as . But, if the function used in the first parameter returns another function, this second function will be fired just before the component is unmounted. Exactly like .

This is the perfect place to remove the component from the listeners array.

The second version

Besides this last modification, we are also going to:

  • Set React as a parameter, not importing it anymore.
  • Not exporting the customHook but, exporting a function that returns a new customHook according to parameter.
  • Create a object that contains the value and the function.
  • Replace the arrow functions for regular functions in and , so we can have a context to bind the to .

Because we have a more generic Hook now, we have to setup it in a store file.

Separating actions from components

If you ever worked with complex state management library, you know that it is not the best idea to manipulate global state directly from the components.

The best way is to separate the business logic by creating actions which manipulate the state. For that reason I want that the last version of our solution doesn’t give component access to the function, but a set of actions.

To work that out, our function will receive an object as a third parameter. Regarding that, there are somethings that I want to add:

  • Actions will have access to the object. For that reason, actions may read the state with , write state through and even call other actions using .
  • For organization, the actions object may contain other actions’ sub-objects. So, you may have an or a sub-object with all counter actions called with .

The final version

The following file is the actual file in the NPM package .

Examples of use

You will never need to touch the again. You may focus now on your application. Here are two examples of how to use it in real life.

Several counters, one value

Add as many counters as you want, it will all share the same global value. Every time one counter add 1 to the global value, all counters will render. The parent component won’t need to render again.

Click in “Open in Editor” to view the code in a new tab

Asynchronous ajax requests

Search GitHub repositories by username. Handle the ajax request asynchronously with async/await. Update the requests counter on every search.

Click in “Open in Editor” to view the code in a new tab

And there we have it!

Our very own state management library with React Hooks!

Update — September 2019

On version 0.1.10 we add a important feature to the library. Now we can map a subset of the global state before use it. This will avoid unnecessary renders on every global state change.

On the following example, we have 2 counters on global state: counterA and counterB. As you add values to the counterA, the counterB component will not re-render and vice versa.

Try the button Add 10.000 CounterB components. It will make update the value of counterB very slow, but update counterA will continue fast.

JavaScript In Plain English

Show some love by subscribing to our YouTube channel!

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

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