Managing global state with React’s Hooks & Context API

Alternative to Redux for complex React application

In complex React application with multiple components, there is requirement for global state management. As of now most popular approach for global state is Redux, but with new changes in React there might be space for global state management using just React. However note that this approach is not necessarily performance improvement, but rather an approach to remove external package.

Please follow up on Hooks and Context, to familiarize with later approach.

React state management before Redux

In order to understand, React state management and Redux role in that, lets get started how state management was achieved previously using React.

This is simple global state management approach, and kind of looks messy. Here <App> component will keep global state as its this.state. It will be passed to child components as props. When this.state change is required, there will be function at root<App> component level using this.setState. However when child component needs to change global state, these callback functions (Eg: changeLanguage), will have to passed as props. In above example <LanguagePicker> will execute callback function and it’ll change state in <App> root component, and updated state again passed to <Lang>.

As seen, this will be mess for large number of components when single complex store have to be managed at root level. Moreover props drilling will occur where at each child component, all props passed should be mapped to its child. All callback functions have to be defined at <App>, and thereby all logic should be handled at root level. Thereby different approach is required for complex application, for simplicity and separation of concern.

Global state management using Redux

Here, its assumed that y’all are familiar with Redux approach and wouldn't go into in depth of configuring and using. Simply Redux will manage global store within the application. Within the React application each component can directly access this global store, and only acquire whats required. Any changes that needs to be applied to store will be done through actions and reducers. This means its one-way data binding in Redux, where React application would not directly manipulate global Redux store, but rather invoke functions with logic to do so.

Image Src: esri.com

Here above entire application wouldn't be re-written with Redux, as it out of scope of this article. But here is how react components will interact with redux store using react-redux connect function.

Here <Menu> component is connected with Redux store using connect function. Here values are manipulated using following functions.

export default connect(
mapStateToProps, → GET FROM GLOBAL STORE
mapDispatchToProps → SET TO GLOBAL STORE
)(Menu)

Here without any intermediary components, Redux store can directly be connected to required component. This will reduce unnecessary re-rendering and can divide complex application into different segments.

Note that this is not necessary performance advantage over using Redux, but rather approaching its usage using plain React. Performance might be lacking due to unnecessary re-rendering that happens in below approaches, where components be rendering even though that segment is not used by that component.

Putting it plainly, this is just keeping state at <App> level, but rather avoiding props drilling using React context.

Global state with State Hook and Context

This implementation works with functional components, and React hooks introduced. In <App> component, state can be initiated by useState. Here store is organized for two separate state hooks: { lang: …, color: … }. This global store create at root level will be passed through context provider to underlying components. Within the child component, access the context consumer value, to read or write global store.

useState + useContext → Global Store

When creating the global store, initiated state hooks are renamed as get and set for ease of use. As example context.lang.get & context.lang.set('.'). Also note that as context was use props drilling through intermediate components was avoided. Moreover, component can include required logic.

Global state with Reducer Hook and Context

Most of React developers, are now familiar with Redux based approach for state management. Thereby similar global state can be achieved via hooks and context, through using useReducer.

In this example context value or global store will return {state, dispatch}. In comparison, state acts asmapStateToProps while dispatch corresponds to mapDispatchToProps.

useReducer + useContext → Global Store

global-store-hook: a npm package

As seen above with simple usage of react hooks and react context, we are able to build up global store for react application. This global store can be published as npm package, so it could be used easily in application.

This simple npm package is created by me here, named global-store-hook. Here its implementation follows state hook and context hook combination discussed above. This is just an elementary package for global store, and there is plenty of room for improvement. Its used here just to demonstrate purposes.

Here store can be initiated in format of object. As an example:

const init = {
lang: 'en',
color: 'blue'
}

Afterwards this store can be easily be read as store.get('lang') and updated as store.set('lang', 'fr').

Lets get started with this package by importing providers and consumer.

import {GlobalStoreProvider, GlobalStore} from 'global-store-hook';

Lets initiate provider as such as we have done in <App> earlier:

<GlobalStoreProvider initValues={init}>

And within application, store can be easily manipulated as <MenuItem>:

const store = GlobalStore();<p>Theme colour: {store.get('color')}</p><button onClick={() => store.set('lang', 'en')}> English </button>

As seen, global store can be easily used by this package. Lets create our previous application using this application.

As seen its pretty easy to use, but there lots of room for improvement. This package was published for demonstration purpose.

Potential improvements include:
→ Conditional re-rendering dependent on store usage
→ Support from nested store values. (Multiple context or hooks.)

If you want to make improve this package, and contribute to build more robust global store, here’s source code:

Finally, You’all should be familiar with using React hooks and context to build global store from scratch for React application.

Full Stack Developer | BiBi

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