React Hooks: useState, useEffect, and useContext

In order to use React to its full potential, one must learn about React hooks and how they can be used to write great applications.
First lets look at what problems existed prior to hooks. At the 2018 React Conference the React team talked about the three major problems that existed with React: Wrapper Hell, Huge Components, and Confusing Classes.

In their attempts to solve each of these problems individually they found
that solving one made the others worse. For example, when they tried to solve Wrapper Hell by putting more logic into the components, the components became larger and harder to refactor. On the other hand, when they tried to split the components apart into smaller pieces and reuse those, they ended up with more nesting in the component tree and Wrapper Hell returned. So they started to approach it as one singular problem instead of three individual ones.

From there they developed hooks. A hook is a function provided by React that lets you hook into React features from your function components.
Today I want to dive deeper into three particular hooks:

useState

This was the first hook ever seen by anyone outside of the React team. During the 2018 conference, a demo was given to introduce hooks and useState provided those in attendance with their first glimpse into the future of React. This hook returns a stateful value and a function to update it.

In this example upon the initial render, the returned state (state) is the same as the value passed as the first argument (initialState). The setState function is then used to update the state. It accepts a new state value and completes a re-render of the component. On each of the following re-renders, the first value returned by useState will be the most recent state after applying updates.

Here’s a very basic example of useState and how we can use it to update a counter. We set our const which includes a value and a function equal to our hook, useState. We then use an onClick to access the setCount function that utilizes the hook to update our count by 1 on every click.

FAQ’s directly from the React js docs

What does calling useState do?
It declares a “state variable”. Our variable is called count but we could call it anything else, like banana. This is a way to “preserve” some values between the function calls — useState is a new way to use the exact same capabilities that this.state provides in a class. Normally, variables “disappear” when the function exits but state variables are preserved by React.

What do we pass to useState as an argument?
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.

What does useState return?
It returns a pair of values: the current state and a function that updates it. This is why we write const [count, setCount] = useState(). This is similar to this.state.count and this.setState in a class, except you get them in a pair.

useEffect

This hook allows you to perform side effects in function components.
Lets look at the counter example again but add in our new hook, useEffect.

As you can see this code is the same as our previous example except we have added the useEffect lines. In this portion of our code we set the document title to display a message that updates via our useState. So as the state updates, so does our useEffect.

Again we can refer to the React JS docs to answer some FAQ’s about useEffect.

What does useEffect do?
By using this Hook, you tell React that your component needs to do something after render. React will remember the function you passed (we’ll refer to it as our “effect”), and call it later after performing the DOM updates. In this effect, we set the document title, but we could also perform data fetching or call some other imperative API.

Why is useEffect called inside a component?
Placing useEffect inside the component lets us access the count state variable (or any props) right from the effect. We don’t need a special API to read it — it’s already in the function scope. Hooks embrace JavaScript closures and avoid introducing React-specific APIs where JavaScript already provides a solution.

Does useEffect run after every render?
Yes! By default, it runs both after the first render and after every update.
Instead of thinking in terms of “mounting” and “updating”, you might find it easier to think that effects happen “after render”. React guarantees the DOM has been updated by the time it runs the effects.

useContext

This hook accepts a context object that comes from the call of React.createContext(). After the call, a current context value returns for that context. This gives us quick and easy access to the context of our React app.
It works with the React Context API and prevents us form having to manually pass props down to different levels.

Most of the React Hooks give function components capabilities they didn’t have before. The useContext hook is a little different though: It just makes things nicer.

So lets look at the old way of using context first.

In the above example we use createContext in the React API to create an object with two values, Provider and Consumer. We then use Provider inside of our App function to make the value available to the children. Lastly, we create the function Display so the Consumer can grab the value from context. This component doesn’t get any props.

So, with useContext we can rewrite the Display function to look something like this:

Here we simply call useContext and pass in the context object we got from React.createContext and we get the value. It’s as simple as that.

The only thing to keep in mind is when you call useContext you need to pass through the entire object and not just the Consumer or Product.

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