React useState and useEffect - A Beginner's Guide

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.

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the Beginner's Guide to Real World React course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to Beginner's Guide to Real World React, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course Beginner's Guide to Real World React
  • [00:00 - 00:14] So, lesson 2, common hooks demoed. Arguably, the most common hooks will encounter our use state, which is used to interact with the component state and use effect, which can be best thought of as replacing the react lifecycle events such as component did mount and component did update.

    [00:15 - 00:23] Before we move on to our big project in this module though, let's take some time to familiarise ourselves with the use of these two most common built in hooks. So, project setup.

    [00:24 - 00:32] We're going to introduce the create react app in the next lesson as a great way to build new react project. For now though, we're going to keep things simple and familiar by using parcel.

    [00:33 - 00:40] js to setup our project and bundle and run our react code for these examples. The first thing to do is to configure parcel.js.

    [00:41 - 00:51] So I've got a brand new folder here open in Visual Studio Code. I'm going to navigate to the terminal window here and initialize our project by running yarn init.

    [00:52 - 00:57] Yes, with the Y flag. Let's install the packages we need.

    [00:58 - 01:13] Using yarn add react and react DOM. And finally, if we open up our package.js and file, let's add the following config so we can call yarn start to run the project.

    [01:14 - 01:31] So we'll add the scripts property and then in here we can add the start command and this will be very similar to the first demo that we did, parcel index.html. And we'll give that a save.

    [01:32 - 01:44] Now our project setup and ready to run, we need to add the necessary files to our project before we fill them out. So over in the file window here, we're going to add an app.js component.

    [01:45 - 01:58] We're going to add index.js which will be our starting point. Stiles.css to hold our styling for the two examples.

    [01:59 - 02:16] The use effect example.jsx which will be our use effect example component. And then finally our use state example.jsx which will be our use state example component.

    [02:17 - 02:24] Use state example and use effect example where we'll do the main body of our work here. So let's get the other file set up before we explore our example components.

    [02:25 - 02:34] So the first thing is over in index.js here. So over in this index.js file, this will be our main entry point for parcel to start loading our JavaScript from.

    [02:35 - 02:52] We'll import our main app component here and call react DOM's render method to mount it to the HTML element in our index.html file. So I'm going to start by importing react from react and import react DOM from react DOM.

    [02:53 - 03:11] I'm going to import our app component from app. And then finally as you may remember from the first example that we did, we call the react DOM dot render method and we have to pass it a component or something to mount.

    [03:12 - 03:21] So in our case, this will be our app component and then we have to tell it where to mount it. So this will be document dot query selector.

    [03:22 - 03:30] And we're going to do the same thing as we did before. We will give this an ID of output which we'll find in the index.html file.

    [03:31 - 03:36] So that's our index.js file DOM. So next things next, our app.js component file.

    [03:37 - 03:45] So in our app component, the main starting point for our react app, we're going to use a hook here, the use.state hook in fact. So let's map this file out.

    [03:46 - 04:05] So we're going to import react and the use.state hook from react. We're going to import our styles dot CSS file and then we're going to load our components here.

    [04:06 - 04:11] With our imports done, we can define the main component body. So we're going to do an inline export again.

    [04:12 - 04:30] So export default props, give it an arrow function and then we're going to immediately define two variables in the array, destructed array. So this will be example and set example.

    [04:31 - 04:51] And then we'll define, we'll call the use.state hook and pass it in a string which will be use.state example and then we'll define our return JSX. So we're going to use the react fragment shortcut again and then we'll define the rest of the body here.

    [04:52 - 05:01] So here we're importing our two example components at the top, use.state example and use.effect example. I'm using the example value in state to determine which one to show.

    [05:02 - 05:19] If example set to use.state example, then we'll show use.state example dot JSX component otherwise we'll show the use.effect example component. And you can see here we have two buttons as well that both call the set example method from our use.state hook which will in turn change the child component which is displayed.

    [05:20 - 05:38] So you can see we're using JavaScript's ternary operator here to basically evaluate if example from use.state is equal to use.state example by default, then it will render the use.state example component otherwise it will render the use.effect example there. And that's our app.js file done.

    [05:39 - 05:55] Over in 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. However, we've added a couple of extra layout selectors at the bottom to add some flexbox support and additional styling to some form elements such as a select and label .

    [05:56 - 06:04] I'm just going to copy this in but you can find these styles from the course material. The last file before we move on to our actual example component is the index.

    [06:05 - 06:14] html file. Now 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's going to look like this.

    [06:15 - 06:31] So we'll need a HTML element and a head with a title and the title hooks example demo. We're going to need the body tag and then we will create a div with the idea of output.

    [06:32 - 06:50] And then finally we need a script tag which will have a source attribute which will just be our index.js which is our starting point for the JavaScript in our project. So with the basic file setup and ready to go, let's take a closer look at the use.state and use.effect hooks.

    [06:51 - 06:59] Over in the use.state example component I've just added some quick code to illustrate some talking points about the use.state hook. This isn't going to be part of our component.

    [07:00 - 07:11] So the use.state hook is a direct replacement for the class based state that you'll see used in this fashion here. If you want to update state you will call this.setState and pass it in an object with some properties and some values within that object.

    [07:12 - 07:26] And if you want to use the state you will simply call it with the curly braces and this.state.whatever the property is. As you've already seen in the previous module the use.state hook has a very simple syntax for setting and retrieving values from it.

    [07:27 - 07:47] So if we were going to do this first example here we're using hooks we would have this with the initial declaration where we have the destructed array with a pairing of the name of the property instead that you want to set and then the setting method which is normally the same name with set on it. And then we call the use.state hook passing in the initial value there.

    [07:48 - 07:55] If you want to update this state value you'd simply call this.setState method. So set name of value and then pass in the new value there.

    [07:56 - 08:07] And using it is even simpler we'd just call it with the curly braces then the name of whatever the value is instead. So 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.

    [08:08 - 08:20] Any valid JavaScript primitive value, array, object and even function can be passed into and stored instead. So the convention is to have distinct declarations for multiple values unless they're logically able to be kept together such as form values.

    [08:21 - 08:32] In the first group you can see that we've got singular values such as an integer, zero and 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 use.

    [08:33 - 08:48] However, for the form values variable we're calling use.state and passing in an object with multiple properties one for name, email and message that each represent a form field value. We could have easily separated those out into their own use.state calls like this too.

    [08:49 - 08:57] This is absolutely fine and you'll see this approach quite frequently. As with a lot of things in development there's a lot of personal preference and trade-offs on how you tackle a problem and implement a solution.

    [08:58 - 09:11] For me it makes sense to group together closely related slices of data such as a collection of form field values into a single place i.e. the form values variable here. But it does add a little bit more overhead and dealing with updates to any particular form fields value.

    [09:12 - 09:28] Conversely if you have a really large form with a lot of field values breaking each one into a separate call to use use.state could potentially create a lot more code for you to manage and a very large component. With that explanation in the bag let's build a little example app to demonstrate how to use use.state and the sorts of values that it can be used with.

    [09:29 - 09:39] Let's get rid of everything in this file. I make sure you've got use.state example.js.open and the first thing we'll need to do is import react and create the empty component skeleton.

    [09:40 - 09:55] So we'll import react and then we'll just define our component here as an arrow function into a const. And for now we'll just return the empty fragment.

    [09:56 - 10:05] Well export by default our use state example. So we want to take a look at how we effectively use the use.state hook here.

    [10:06 - 10:15] To do that we're going to build a HTML form that will update values in our component state and display a nice message to our user once it's submitted to form. To do that we'll need a few things.

    [10:16 - 10:23] An object in state track our state values. A value in state to determine if we should show the message i.e. has the form been submitted or not.

    [10:24 - 10:32] Methods to handle changes in the form elements and form submission and a HTML form. Our component is looking a little bit bare at the moment so let's fill that out .

    [10:33 - 10:42] So the very first thing we'll do is add our state values and items right at the top of the component. So for this we're going to create two instances of the use.state hook.

    [10:43 - 10:52] So this will be show message and set show message. Remember the convention where the name of the item in state is one thing and then we take that name and just add set to it.

    [10:53 - 11:00] So show message and set show message. We call the use state hook here and we'll give that a boolean value of false.

    [11:01 - 11:10] The next one we'll define will be the one to hold our form values. So we'll simply call it form values and set form values.

    [11:11 - 11:33] For this we'll call the use state hook and we'll pass in object with three key value pairs to represent the three form fields that we're going to put into our form. So we'll say name and set that to an empty string, edge to an empty string and fruit.

    [11:34 - 11:39] Also to an empty string. You can see that we really can start just about anything you want into state.

    [11:40 - 11:54] Our first state variable show message is going to hold a boolean value while our second form value holds an object with some of the default key value pairs in there that we 're going to track the input from our user. Now you don't have to add the keys in like we've done here but I think it's good practice to do so.

    [11:55 - 12:05] 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. Next let's map out our state updating methods or event handlers.

    [12:06 - 12:15] One for a change in any form field values and one to handle a form submission. So our first one will be we'll call handle change.

    [12:16 - 12:30] Remember it's passed a synthetic event object so we'll just call it evt. And next we'll create our handle submit method which again will be passed evt.

    [12:31 - 12:47] Remember you could call that evt or e or event or whatever you wish but evt just makes sense for me evt prevent default and then we'll say set your message to true. So there are a couple of things to notice here.

    [12:48 - 13:01] In the handle change event you can see that 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 updated form values object first.

    [13:02 - 13:26] Using the JavaScript spread syntax here the three dots you can see before form values which will essentially copy everything from the current form values object instead into our updated form values object. Immediately after this we use the bracketed notation passing in evt.target.id to reference a property dynamically on the updated form values object specifically referencing using the form fields id.

    [13:27 - 13:33] If this exists on the object then the value we assign to it e g evt.target. value will be updated.

    [13:34 - 13:46] If it doesn't exist then a new property will be created and assigned to the value of evt.target.value. Finally we can update our form fields object instead by calling the set form values function here.

    [13:47 - 13:56] You could do this all in one line but it's a little neater and more readable to make a copy of the object instead. Update that copy and then supply that method into the updating state.

    [13:57 - 14:08] Do the thing to point out here is our use of evt.prevent default in the handle submit method. For all the event that react passes us is synthetic the form submission caused by the button we add in a moment is very real.

    [14:09 - 14:18] By calling the prevent default method when the form submits we'll stop the form from triggering a complete page reload. If that happens we'll lose our state values and our apple produce unintended results.

    [14:19 - 14:33] Other than that the handle submit method is quite simple we change the value of show method instead to true which will be used later in our returned JSX. Now we're on to the final piece of the puzzle which is to add our JSX into the return method so we can actually render something useful to the user.

    [14:34 - 14:47] First a little message introducing the app to the user. And then we will add our react fragment and add a little message.

    [14:48 - 14:54] Next we can add our HTML form. And there shouldn't be anything too unfamiliar here just a HTML form.

    [14:55 - 15:02] There are a couple of things to highlight though. Notice on our labels that we're using HTML for instead of the standard for attribute.

    [15:03 - 15:08] This is because we're still in JavaScript land and for is a protected keyword. Much like you'd use in a for loop.

    [15:09 - 15:18] You can use it but react will complain giving warnings in the browser and any tools like a yes lint will also notify you about this. Stick to HTML for when using an attribute on labels in react.

    [15:19 - 15:34] Each of our HTML elements inputs and select is setting the value attribute here . Using a named key from our form value state object they also each reference the same change event handler handle change here that we defined earlier.

    [15:35 - 15:46] Finally, there's no event handler attached to this button within our form. This is because the button will trigger a form submission event by default when it's clicked so all we need to do is attach our handle submit event handler to the form itself.

    [15:47 - 16:02] Of course, once we've collected our user data and submitted it, we need to display a little message. So underneath form we will add show message and then some JSX return if show message is true.

    [16:03 - 16:15] Within this we have a couple of simple paragraphs that we reference the value from state. We also wrap this entire block in a simplified logic expression with a show message and and then whatever is in this parenthesis here.

    [16:16 - 16:28] What happens here is that JavaScript evaluates the left side of the expression, show a message and if that's false it doesn't look at the right side of the expression. However, once your message is true then it would evaluate the right hand side which will essentially render our JSX block.

    [16:29 - 16:38] And that's our use state example component complete. The use effect hook is a little more complex to understand than its relatively simple use state cousin.

    [16:39 - 16:56] React has several lifecycle methods that have triggered during specific parts of components journey from being mounted to any update and finally when it unmounts. Before hooks developers would have to tie update into these lifecycle methods tasks such as fetching data, handling updates to props values, cleaning up data handling or subscriptions to APIs.

    [16:57 - 17:04] As we saw in lesson one this leads to a messy and very complex components. What use effect gives us is a combined method that runs on each render for component.

    [17:05 - 17:18] It can be used multiple times to separate out any distinct logic and it can also be passed an array of dependencies which React will monitor for changes. Should any of those dependencies change only then would that particular use effect call be executed.

    [17:19 - 17:29] Additionally some work requires a clean up phase, eg subscriptions to external data sources. For these tasks you can return a function as part of your use effect call that will carry out any clean up code you need.

    [17:30 - 17:37] You can think that this is replacing the component will amount lifecycle events . Let's look at the syntax a little closer to get an idea of how it works.

    [17:38 - 17:51] Once again over in our use effect example component I'm just going to quickly copy in an example here. We've got simple use effect declaration which is we call the function use effect and we pass it a function.

    [17:52 - 18:02] And then you can see we've got some kind of clever data logging service.log function that we pass in an exciting log entry. But this now this one will be called on each render.

    [18:03 - 18:18] On Unmount we might need to clean it up so you can see on Mount and re-render. We can subscribe to this product list that's what will be called on Mount and on re-render and we return a function that will be called on render and on Unmount.

    [18:19 - 18:37] If you want to use dependencies then we can use it with this array where we pass in some kind of value, some kind of dependencies and this use effect will only be run when props.customer.id changes. So now when we know a little more about the use effect hook we can build out our component.

    [18:38 - 18:47] Empty this out and make sure you've got open your use effect example.jsx component. Now we'll get the basics component scaffolding in here as well as our React Im ports.

    [18:48 - 19:14] So we're going to import react as well as the use there hook and the use effect hook from react. And we'll define our component so we const use effect example and again we'll do our arrow function and we'll just return the empty react fragment.

    [19:15 - 19:23] Default export and give it a save. In this example we'll be building a really simple gallery that loads everyone's favorite dog pictures.

    [19:24 - 19:30] For this we'll be using the excellent dog CEO API. For the component we'll need to accomplish a few things.

    [19:31 - 19:41] We need to set our API URL for loading in the pictures. We need to add two variables instead, one for holding the image URLs of our dogs and another loading flag that we can use to show a loading message.

    [19:42 - 19:50] We need to create a function to actually go and load our dog pictures. Two use effect calls, one for an initial load and one for subsequent loads when the user presses the button.

    [19:51 - 19:56] We need a button for the user to trigger a new set of dog pictures and the gallery itself. So let's get building.

    [19:57 - 20:16] The very first thing to do is to define some variables, namely our fixed API URL and some flexible state values. So right inside our component we create a const that is API based URL and this will be the URL of the API that we get from the dog.seo website.

    [20:17 - 20:43] Next we'll use our use set hook to create a variable that will store dog image URLs which will be an array and for this we'll just set it, there's initial value as just an empty array. Lastly we'll create our load pictures flag which will be a boolean value set to false initially.

    [20:44 - 20:55] Nothing too tricky so far. The dog.seo API address here will return as a single image of a dog, that's not good, so we need to append a random number onto this later so we can get a nice amount of dog images back.

    [20:56 - 21:09] Without state variables dog image URLs is set to an empty array to begin with but it will hold a list of pictures once the API has been called. With load pictures we set it to false for now but we can use this to toggle whether the app is in the middle of loading data or not.

    [21:10 - 21:23] Of course we need to call the API to get the pictures in the first place so we 'll define that next. So we'll create a new function, load dog pictures.

    [21:24 - 21:37] So with num to load we're using the math.random function and we're generating a random number between 1 and 10. Next we'll call in the dog.seo API, appending this random number onto the end to return as that number of dog or picks.

    [21:38 - 21:50] And I've used the native browser fetch method here but in a realistic setting you might need to consider browsers apart and you might need to look up using a polyfill or external utility library like the Axios project. The process is straightforward.

    [21:51 - 22:03] Fetch calls the API, we massage the raw response into JSON and then we consume that JSON as the object data. Extracting a message object defined by the dog.seo API docs which just happens to be an array of image URLs.

    [22:04 - 22:12] We set this array instead using our set dog image URLs method returned to us by the use state hook up here. Now to create the use effect calls.

    [22:13 - 22:22] We're going to use the use effect hook in two separate calls here. One that will be used on initial mount of the component and the other will trigger a new load of pictures when state value load pictures changes.

    [22:23 - 22:32] So let's do our first one. We call the use effect hook, we pass it in an anonymous arrow function.

    [22:33 - 22:38] We're actually using a bit of a react trick here. By passing this use effect function an empty dependency array.

    [22:39 - 22:52] We're effectively telling react to execute the effect but only once on very first mount. We're doing that here because we want to have some dog pictures available on the component first mount but not each and every time anything happens such as when the component updates.

    [22:53 - 23:06] We do however want to trigger a new fetch when the user clicks the load more pictures button. When they do that the value instead for load pictures will change and we can have react watch this value and execute our second effect only when that changes.

    [23:07 - 23:12] Let's define our second use of the use effect hook now. So we'll say use effect.

    [23:13 - 23:21] We pass it anonymous function. Set load pictures into the dependency array.

    [23:22 - 23:33] So you can see with this use effect call we supply load pictures as a dependency to the use effect hook. When this load pictures value changes react will execute whatever we supply to the function.

    [23:34 - 23:49] In this case we make sure to check that it is set to true here calling the API again before setting its value back to false which will enable the button to work again. The key now among you will be asking at this point won't this just trigger the effect to be called again even when load pictures is set back to false.

    [23:50 - 24:00] The answer is yes but by checking to see if it's set to true at the start of the function we avoid some horrible infinite loop scenario. Now it's time to add the button and the gallery JSX.

    [24:01 - 24:25] So with all of our logic and players we can process the images and display a lovely gallery of our good dogs to our users. Starting with a title we then add a button that simply sets the load pictures boolean value instead to true as we discovered when mapping out the use effect calls because react is watching this value as a dependency it will automatically trigger a fetch of some new dog pictures.

    [24:26 - 24:40] Under this we display a message to the user based on the value of load pictures loading if it's set to true and the number of dog pictures we can expect to see if false. And the part that we've all been waiting for that pictures themselves.

    [24:41 - 24:52] So we're using the dot map function built into JavaScript arrays as we step through our array of dog pictures outputting an image tag. Notice that we've added an extra attribute you might not be familiar with right away.

    [24:53 - 25:02] This key attribute is another React specific attribute that is needed when rendering a list of things. It helps react keep track of changes within the list such as if any have been added, removed, etc.

    [25:03 - 25:17] You should supply a unique identifier to each item in a list to give the elements a stable identity. The nice thing about the dot map function is that if we have an empty array like when we have when we initialize it to the empty brackets at the beginning of the component nothing's output to the user.

    [25:18 - 25:29] The very last thing to do is to fire up our app using yarn star in the terminal and enjoy some wholesome dog pictures what the internet was made for. The back over in my terminal we can run yarn start.

    [25:30 - 25:36] You see we've got a server running a local host 123. So you should see something like this.

    [25:37 - 25:54] So this is our main starting point and you can see we've already loaded the use state example. If we type in something here so we'll call me robkendel and shockingly I am 38 years old and my favorite fruit we will say is strawberries.

    [25:55 - 26:05] If we submit this we get a lovely message saying hi robkendel what a lovely name I can't believe you're only 38 years old that's no edge. It's really really good to hear you say that react app.

    [26:06 - 26:13] Your favorite fruit can't be strawberries mine too. So you can see this message is dynamically created for us based on the information we've provided in these boxes.

    [26:14 - 26:30] If we say Batman and if we said that was question mark and then pairs you can see that it's updated for us dynamically based on our values instead. And finally what we've all been waiting for some pictures of dogs so we'll click over on the use effect example.

    [26:31 - 26:42] And there we go so we've loaded in seven pictures and it's told us that we've got seven pictures. All happy good boys and we can click the load mark pictures it'll go off and get us just two.

    [26:43 - 26:47] We click it again it'll get as a random set another seven. There we go great.

    [26:48 - 26:51] So these are two good examples of you state and the use effect hooks.