This video is available to students only

Common Hooks

In this lesson we'll take a look at the most common Hooks you'll come across and learn how to use them in your apps.

Common Hooks demoed#

Arguably the most common Hooks you’ll encounter are:

  • useState - which is used to interact with a component’s state.

  • and useEffect - which can be best thought of as replacing the React lifecycle events such as componentDidMount and componentDidUpdate.

Before we move onto our big project in this module, let’s take some time to familiarize ourselves with the use of these two most common built-in Hooks.

Project setup#

We're going to introduce Create React App in the next lesson as a great way to build new React projects. For now, though, we're going to keep things simple and familiar by using Parcel JS to set up our project to bundle and run our React code for these examples.

Configuring Parcel JS#

Create a new folder and open it in VS Code. Navigate to the terminal and let’s initialize our new project:

yarn init -y

Next, let’s install the packages we need:

yarn add react react-dom

Finally, open up your package.json file and add the following config so we can call yarn start to run the project:

Creating the files#

Now our project is set up and ready to run, we need to add the necessary files to our project before we fill them out.

  • App.js

  • index.js

  • index.html

  • styles.css

  • UseEffectExample.jsx

  • UseStateExample.jsx

UseStateExample.jsx and UseEffectExample.jsx are where we’ll do the main body of our work here, so let’s get our other files set up before we explore our example components.

index.js#

This will be the entry point for Parcel to start loading our JavaScript from. We import our main App component here and call React DOM’s render() method to mount it into the HTML element in our index.html file.

App.js#

In our App component, the main starting point for our React app, we’re using a Hook, the useState Hook in fact.

Let’s take a look at the file in full:

Here, we’re importing our two example components, UseStateExample and UseEffectExample and using the example value in state to determine which one to show.

If example is set to the string ‘UseStateExample' then we’ll show the UseStateExample.jsx component, otherwise, we’ll show the UseEffectExample.jsx component.

We also have two buttons that both call the setExample() method to update the example state value, which will, in turn, change which child component is displayed.

styles.css#

Much of the styles here are the same basic styles from our very first example that we built in Module 2, the Greeting App. We’ve added a couple of extra layout selectors at the bottom to add some flex box support and additional styling to some form elements, such as a select and label.

index.html#

Once again, our index.html file simply provides us with a basic entry point for Parcel to follow and find our JavaScript starting point.

It looks like this:

With the basic files set up and ready to go, let's take a closer look at the useState and useEffect Hooks.

The useState Hook#

useState is a direct replacement for the class-based state you’ll see used in this fashion:

As we’ve already seen in the previous module, the useState Hook has a very simple syntax for setting and retrieving values from it.

You’re not limited to what you can store inside this state Hook, just like you’re not limited with state used in a class component. Any valid JavaScript primitive value, array, object, and even function can be passed into and stored in state.

The convention is to have distinct declarations for multiple values, unless they’re logically able to be kept together, such as with form values.

In the first group, you can see that we've got singular values such as an integer, '0', an empty array, and a null value. These are all distinct pieces of state and declared in their own variable pairs, each using a separate call to useState. However, for the formValues variable, we're calling useState and passing in an object with multiple properties, one for name, email, and message, that each represents a form field value.

We could have also separated these values out into their own useState call like this:

This is fine and you'll see this approach quite frequently. As with a lot of things in development, there is a lot of personal preference and trade-offs on how you tackle a problem and implement a solution. For me, it makes sense to group closely related slices of data, such a collection of form field values, into a single place (i.e. the formValues variable above), but it does add a little more overhead in dealing with updates to any particular form field's value. Conversely, if you have a really large form with a lot of field values, breaking each one into a separate call to useState could potentially create a lot more code for you to manage and a very large component.

With the explanation in the bag, let’s build a little example app to demonstrate how to use useState and the sorts of values it can be used with.

First things first: open up the UseStateExample.jsx file, where we’ll need to import React and create the empty component’s skeleton:

We want to take a look at how to effectively use the useState Hook here. To do that, we’re going to build an HTML form that will update values in our component’s state, and display a nice message to our user once they’ve submitted the form.

To do that, we’ll need a few things:

  • An object in state to track our state values

  • A value in state to determine if we should show the message (i.e. has the form been submitted?)

  • Methods to handle changes in the form elements and form submission

  • An HTML form

Our component’s looking a little bare at the moment, so let’s fill it out.

Adding in state#

The very first thing we’ll do is add our state values and items, right at the top of the component.

You'll see that we really can store just about anything you want into state. Our first state variable, showMessage is going to hold a boolean value, whilst our second, formValues holds an object with some default key-value pairs in there where we’ll track the input from our user.

You don’t have to add the keys in like we’ve done here, but it’s good practice to do so. It’ll let you get an idea of what data our form will capture and what the expected type of that data will be, without having to run anything.

Event handling methods#

Next, let’s map out our state updating methods, our event handlers: one for a change of any form field values, and one to handle the form submission.

There are a couple of things to notice here. In the handleChange event, you can see we’re still using the evt.target.value to retrieve the current value from the underlying HTML element (e.g. a text input field), but we’re creating a new updatedFormValues object first. We're using the spread syntax (the three dots you can see before formValues) which will essentially copy everything from the current formValues object in state into our updatedFormValues object.