Data is at the heart of all applications. In the last part, you learned how to manipulate props through components, adapting them according to the data you wanted to render.
But how can users interact with this data? Connecting with the app, entering information, and modifying the data displayed? How do we hold the data they enter?
That’s exactly what we’re going to deal with in this chapter. You can do all of this using state!
You had a brief introduction to state in the last chapter, but it’s now time to go into a bit more detail.
Use Stateful Components
Local state is present within components, holding their value even if the application re-renders. You can refer to these components as being stateful.
Let’s go back to Cart.js
. For now, we’re only going to allow users to add Montsera to their cart, so we’ll delete everything else.
Start by importing useState
with:
import { useState } from 'react'
Then create a cart
state. With useState
, you need to declare a function at the same time to update this state ( updateCart
), and give it an initial value, which will be 0:
const [cart, updateCart] = useState(0)
You can now add a button to the cart that lets you add monstera with the declared function. In Cart.js
, you end up with:
function Cart() {
const monsteraPrice = 8
const [cart, updateCart] = useState(0)
return (
<div className='jh-cart'>
<h2>Cart</h2>
<div>
Monstera: {monsteraPrice}€
<button onClick={() => updateCart(cart + 1)}>
Add
</button>
</div>
<h3>Total: {monsteraPrice * cart}€</h3>
</div>
)
}
Now, if you click "Add to cart," the cart total is changed according to the number of elements saved in the cart state.
Welcome to the magical world of state! Our cart component has now become a stateful component, thanks to useState
.
In practice, this means that however many times the cart component re-renders, our cart value will be saved.
So what is useState
, then?
Discover the useState Hook
useState
is a hook that lets you add React’s local state to function components.
A hook? What’s that?
A hook is a function that allows you to hook into React functionalities. You can import them directly from React.useEffect
is another hook. There are others that this course won’t cover, but you’ll be able to learn about those in the next React course.
We’ve already used this, but let me show you again:
const [cart, updateCart] = useState(0)
Let’s look at how to build our cart state in a bit more detail. 😉
Understand Hooks
First of all, []
hooks. If you think this syntax looks a bit odd, remember that it’s the same practice you saw in the previous part: destructuring. Here, though, it’s called decomposition because we’re dealing with an array rather than an object.
useState
returns a pair of values in an array of two elements, which we get in the variables cart
and updateCart
in our example. The first element is the actual value, and the second is the function used to modify it.
Without using decomposition, we could have done:
const cartState = useState(0)
const cart = cartState[0]
const updateCart = cartState[1]
In decomposed arrays, you can name variables whatever you like, such as:
const [hi, whatsup] = useState(0)
Set Up State
Let’s look at the parameter passed between brackets to useState: useState(0)
.
As mentioned, this is an initial state, which should be a number, like here, or a string, a boolean, an array, or even an object with several properties.
Create Several State Variables
Let’s improve our cart even more. This time, we want to choose whether to show or hide it. To do this, we’re going to use a state variable in our Cart component.
But we already have one – how are we going to create another? 😱
There are various ways of doing this. The easiest, though, is to use several state variables.
All you need to do is create an isOpen
variable associated with the setIsOpen
function, and set it to false:
const [isOpen, setIsOpen] = useState(true)
To interact with it, you then need to create:
A button for opening the cart, which will be the only component returned by Cart if the cart is closed.
A button to close the cart.
That gives this code:
function Cart() {
const monsteraPrice = 8
const [cart, updateCart] = useState(0)
const [isOpen, setIsOpen] = useState(false)
return isOpen ? (
<div className=jhjh>
<button onClick={() => setIsOpen(false)}>Close</button>
<h2>Cart</h2>
<div>
Monstera: {monsteraPrice}€
<button onClick={() => updateCart(cart + 1)}>
Add
</button>
</div>
<h3>Total: {monsteraPrice * cart}€</h3>
</div>
) : (
<button onClick={() => setIsOpen(true)}>Open Cart</button>
)
}
After adding a bit of style, you get:
See? It’s easy to create several state variables within the same component. Now it’s your turn to have a go! 💪
Give It a Go!
For getting started on this exercise, you’ll find the codebase on branch P3C1-Begin.
For this chapter, create a clear cart button that reinitializes the state in our cart
.
You’ll find the solution on branch P3C1-Solution.
Let’s Recap!
Local state exists within a component: the data will be preserved no matter how many times the component re-renders.
A hook is a function that lets you hook into React functionalities.
useState
is a hook that lets you add React local state to function components.It returns a pair of values in an array of two values, which you get in the variables between hooks.
You must initialize your state with a parameter passed between brackets – a number, a string, a boolean, an array, or even an object.
We’ll take state to the next level in the following chapter, learning how to share state between several components. We’ll improve our cart so that we can update it from our whole list of plants. A bit more realistic, don't you think? See you there!