Getting To Know the useState Hook in React, Part One: Your First State
Introduction
Let’s first ‘hook’ in an introduction (groan)… If you’re new to React, like I was not very long ago, useState might be your first exposure to a React hook. Hook is a fancy term for something that wraps up functionality in a neat package within React that you can easily drop into your code and use when necessary. You can and should create your own when you need to, but some are inbuilt into React — you “get them for free,” so to speak; useState is one of these. It might seem intimidating, but trust me — with what it’s doing under the hood (not to mention that it was a lot more complicated back in old-style React before hooks!), you’ll be singing this hook’s praises in no time.
You can get access to the built-in useState hook by importing it at the top of your page, nestling it in in curly brackets next to where you’ve already imported React:
This is you telling the computer that along with the whole React shebang that lets you set up your lovely React app and start using its main functionality, you also want to reach into React’s built-in bag of tricks via destructuring and pull out that useState hook to require it specifically here. You’ll need to do this for this and any other built-in hooks you’re using at the top of every component where you use useState (and your code editor may even do it automatically for you).
Setting up your first state
Now that you have useState in your virtual toolbox, let’s put it to work. To do this, we need to understand what makes a state. A state behaves like a variable in that it can hold most any data type, from a simple Boolean or string up to a complicated array or object. It’s held (and controlled/manipulated) within a component, and unlike a simple variable, it has a few more bells and whistles. The first step is declaring the state, including the name of the state, its built-in function for changing it, and what value (if any!) at which it begins. It’s conventional to do this at the top of your functional component, so on a line right after your line that declares function ComponentName() { and before any other functions or return.
The anatomy of declaring a state using the new React hooks is as follows, using a destructured array:
This might look a bit jarring and hard to wrap your head around at first, but after a bit of practice, it’ll become second nature. I like to think of state like a dry erase whiteboard. The state’s data isn’t hard-coded with a Sharpie’s indelible ink. It can easily be changed when you purposefully rewrite it, but until you change it, it stays on that whiteboard. To change it, you can wipe it and write something else in its place with the special eraser and pen, the setState function.
Let’s see this in action with a simple example. In an homage to my favourite, grandma-tastic hobby, let’s say that you need to count your stitches as you follow a crochet pattern. If you’re not au fait with crochet, you follow a pattern that tells you how many stitches to make, row by row throughout your project. You might want to write a simple programme that has a button that you press each time you make a stitch, as well as having an area on the screen that displays the current count. You’d set up your state like this:
In this case, our state is called stitchCounter (nice and semantic — it’s best for readability that your states do what they say on the tin), and in its starting position, initial state is 0; you haven’t started making any stitches yet, so you start with zero stitches. The setStitchCounter function, when called, will take in in its parentheses whatever the new state will be; in this case, it should iterate it up by one. It’s convention to call your function that changes the state a name that puts the word set in front of the state name.
Another thing to note is that your component (in this case, our App component), will re-render each time a state changes. Once you move on to useEffect, you’ll learn how to have more flexibility around what renders and when based on changes, but for now, just file the fact that a state change prompts a re-render in your mental back pocket.
Using state dynamically in your code
Let’s set up the state and the function with which to change it within our app. I’ll fire up a new create-react-app project, empty out the sample code in the App component (in App.js in the src folder), and get started by writing what I’ve just described, along with a function that uses that setStitchCounter function to iterate the number of stitches up by one. Each time the function is called, the new stitchCounter value is set to the old stitchCounter value plus one.
So far, so good. We’ve set up the mechanisms behind the scenes. But what about getting that stately goodness to render into something we can see on the screen when we return our JSX at the end of this function? And how do we hook up a button to it? I’m making the assumption here that you’re familiar with the HTML-like JSX and how to use it to render the component onto the page via returning it from the component’s function — if not, give that a Google and try rendering static JSX on the page before you progress to making it dynamic with state.
It’s at this point where the state, stitchCounter, starts acting a bit like a normal variable again. We can wrap it up in a basic <p> tag:
The state needs to be in curly brackets as that’s how we add JavaScript to JSX without just rendering it as text on the page. Otherwise, the page would just say the word stitchCounter instead of the number it holds.
Let’s pop that in our app:
I’ve jumped the gun a tiny bit and wrapped it in a div; don’t forget that in a functional React component, you can only return one thing. Wrapping it in a div, or a fragment if you want to get fancy — a set of empty angle brackets (<> and </>) that handily disappear once rendered — is a nifty way to cheat this. I’ve chosen a <div> here so I can pop in an id for it as a container for eventual styling. In a future refactor, depending on what else is on my page, I should probably change this to a semantic HTML tag instead…
But look at the state I’m in (groan!), rambling away. Let’s bring it back in to state. We have the state displaying on the page as 0, but that’s not going to help us with our stitches, is it? We need a button that utilizes that setStitchCounter via the handleClick() to make it fully dynamic. The button can just be a simple HTML button for now (and styled at will later with CSS), with an onClick react event. Pop that handleClick there, and it’ll fire each time you click the button. Don’t forget the curly braces once again so that the JSX can handle it as JavaScript. Here’s what it looks like:
Just a quick side note about that function before we stick it into our app: Notice how the handleClick doesn’t have () after it. The eagle-eyed Hermione Grangers among you might be waving your hand, ready to tell me that if it had the parentheses after it (so handleClick()), it would invoke immediately once the code is compiled, rather than waiting on the user to click it. Ten points to Slytherin (what can I say — I’m biased!) as this would be right.
Now let’s drop that button into our code:
And there you have it, folks. If you’re coding along, and I hope you are, you now have a button that, whenever it’s clicked, iterates the number displayed on the screen up by one. Hooray!
But don’t rest on your laurels just yet. When you’re ready, continue on to part two where we’ll add another state and explore the concept of a controlled component through an input field to make our stitch counter app even more dynamic.