A Coding Writer’s Guide: React Context API & Hooks, Or The ‘Lite Way’ To State Management

Andrew Ly
5 min readAug 12, 2019

React.js as you may know is considered one of the three most popular JavaScript framework aside from Vue.js and Angular.js in 2019. If you’re asking yourself what that means or you’re just a curious reader who happened to stumble upon this article, then I suggest you prepare yourself for a rigorous head scratching session while muttering “huh?” repeatedly under your breath for the next several minutes.

Now the reason React.js has rapidly become a household name in the programming world is largely due to the fact that it was created and is currently maintained by Facebook, allowing it tons of credibility and stability in terms of application building. This also means that you can be sure to see continued growth in terms of career potential as React.js has produced complementary mobile development language in the form of React Native.

For those who have tinkered with React.js, then you know state management is a cornerstone in this particular framework, and before it was hard to keep track of your state. Redux originated as a supplement to help in this regard as an open source library for state management which was created by Dan Abramov and Andrew Clark in 2015. But the problem with using Redux is that it is arguably one of the harder concepts needed to understand in order to create larger React.js applications effectively. It’s also not officially supported and most of it’s practicality can be boiled down to:

  • If you wanted a global state object
  • If your application is or will be very big
  • If you’re already too deep into Redux, ie. Redux DevTools, Redux Undo, Redux Form, Redux Saga, Redux Persist, and you get the point…

If none of the above applies to you, then you’re in luck! Since version 16.3 of the React.js framework was released, we finally have a stable and officially supported answer for the mid-sized applications (or the ‘lite way’ as I affectionately call it). We call this Context.

Context provides a way to pass data through the component tree without having to “prop drill” or “thread”.

Typically, data is passed top-down from the parent to its child by props. Unfortunately, this can be both confusing and inconvenient depending on the build and amount of components within an application. Well what can we do about this? In essence, Context provides a way to share values like these between components without having to explicitly pass a prop through every level of the tree.

As a good rule of thumb: if you have to pass props down three levels or more, you should probably consider using Context.

Consider this code sample of manually threading through a “theme” prop in order to style the Button component:

class App extends React.Component {
render() {
return <Toolbar theme="dark" />;
}
}

function Toolbar(props) {
// The Toolbar component must take an extra "theme" prop
// and pass it to the ThemedButton. This can become painful
// if every single button in the app needs to know the theme
// because it would have to be passed through all components.
return (
<div>
<ThemedButton theme={props.theme} />
</div>
);
}

class ThemedButton extends React.Component {
render() {
return <Button theme={this.props.theme} />;
}
}

However, with Context we no longer need to prop drill as seen in the code sample provided below:

// Context lets us pass a value deep into the component tree
// without explicitly threading it through every component.
// Create a context for the current theme (with "light" as the default).
const ThemeContext = React.createContext('light');

class App extends React.Component {
render() {
// Use a Provider to pass the current theme to the tree below.
// Any component can read it, no matter how deep it is.
// In this example, we're passing "dark" as the current value.
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}

// A component in the middle doesn't have to
// pass the theme down explicitly anymore.
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}

class ThemedButton extends React.Component {
// Assign a contextType to read the current theme context.
// React will find the closest theme Provider above and use its value.
// In this example, the current theme is "dark".
static contextType = ThemeContext;
render() {
return <Button theme={this.context} />;
}
}

Neat, right? There is a caveat, however. Context should be used when some data needs to be accessible by many components at different nesting levels. Apply it when necessary, otherwise it can make components more difficult to reuse.

Now that you have an idea about Context, let’s move onto Hooks!

Hooks allow you to essentially “hook into” React features such as state inside a functional component, i.e. without creating a class.

For example, useState is a very common Hook that lets you add React state to function components.

useState is a new way to use the exact same capabilities that this.state provides in a class. Typically, variables simply vanish when the function exits but state variables are naturally preserved by React.

The only argument to the useState()Hook is the initial state. Unlike with classes, the state doesn’t have to be an object. We can keep a number or a string if that’s all we need. In our example, we just want a number for how many times the user clicked, so pass 0 as initial state for our variable. (If we wanted to store two different values in state, we would call useState() twice.)

 1:  import React, { useState } from 'react';
2:
3: function Example() {
4: const [count, setCount] = useState(0);
5:
6: return (
7: <div>
8: <p>You clicked {count} times</p>
9: <button onClick={() => setCount(count + 1)}>
10: Click me
11: </button>
12: </div>
13: );
14: }

Let’s break down some of this code sample above to get some better insight.

  • Line 1: We’ll import the useState Hook from React which lets us keep local state in a functional component.
  • Line 4: Inside the Example component, we declare a new state variable by calling the useState Hook. It returns a pair of values which we’ll give names. We are naming our variable count because it holds the number of button clicks. We initialize it to zero by passing 0 as the only useState argument. The second returned item is itself a function. It lets us update the count so we’ll name it setCount.
  • Line 9: When the user clicks, we call setCount with a new value. React will then re-render the Example component, passing the new count value to it.

I know, it’ll take some getting used to. But believe me, it’ll be worth the trouble once you get the hang of it.

With that being said, are Context and Hooks the best thing for React.js users? That’s debatable. As I’ve stated when I started learning CakePHP in another article, it truly depends on what you want to do and where you want to work. New and exciting languages and frameworks pop up all the time, sometimes for short periods and other times they stay for the long haul. But it appears that React.js is here to stay, so why not pick it up if you have the time? Besides, it’s a great alternative to Redux and adding another skillset to your repertoire is never a bad idea.

--

--

Andrew Ly

Founder of Neo Typewriter. He is a published author, podcast host, digital marketer, and full-stack web developer. Read more at: www.andrewjly.com