Events, State, and Forms
Last updated
Last updated
In this lesson, we will look at how to respond to events in React and use those events to manage the ever-changing state in our application.
Table of Contents
State — Data that is used by an application at a particular point in time. State is often mutable, meaning it can be changed over time, usually in response to user actions or other events
Stateful Component — A component that depends on state and is re-rendered whenever the state changes.
Hooks — Functions that provide a wide variety of features for React components. They all begin with use()
.
useState
– A react hook for managing state within a React component. It returns an array with a state value and a setter function. It triggers the component to re-render when the state changes.
Lifting state up — A practice where state is defined in a parent component so that it can be used by its child components.
Controlled Form — A form whose value changes are controlled by a piece of state.
In this lesson, we'll be using an app called instapets
to demonstrate building stateful components. A stateful component is one that depends on state and re-renders whenever the state changes.
State is the data that is used by an application at a particular point in time. State is often mutable, meaning it can be changed over time, usually in response to user actions or other events
Right now the app is not stateful. It renders 3 hard-coded pet pictures, the form doesn't work and neither do the "Like" buttons.
Let's build this thing!
Let's tackle the likes buttons first.
Each InstagramPost
component renders a picture, a caption and a button to increment and display likes.
Notice how we added an
onClick
prop with thehandleClick
callback function.
A stateful component is one that renders state — data values that may change.
Let's make likes
a piece of mutable state.
We want to update likes
each time we click on the Like
button. So, maybe this will work?
While this does increment the likes
value, it doesn't cause the component to re-render because React isn't watching this value for changes.
useState
So how do we make the component re-render with the updated likes
value?
We need a hook. Hooks in react are functions that perform a variety of jobs. They can be identified by their name which starts with "use":
useState()
useEffect()
useNavigate()
useParams()
useContext()
etc...
The useState
hook allows us to create a piece of state that React will watch and when the state changes, it will re-render.
Here's how it works:
useState
is a named export of the react
package (note the {}
around the function in the import
statement).
useState(0)
returns an array with two values:
A piece of state data (likes
) with a starting value (0
)
A "setter" function for updating that state data (likes
) and re-rendering the component
The convention is to name state variables like [something, setSomething]
using array destructuring.
When the event handler is clicked, we'll invoke setLikes
which either accepts:
the new value that we want to set likes
to or...
a callback function for turning the current value of likes
into the next value of likes
.
As we saw, incrementing likes
directly does not cause the component to re-render
setLikes
will cause the component to re-render with the provided value as the new value for likes
Quiz!
Why did we pass in 0
when we invoked useState
?
What does useState()
return?
What does setLikes()
do? What kinds of inputs does it take?
setLikes
does NOT change the value of likes
Interestingly setLikes
does NOT change the value of likes
within the handleClick
callback. It tells React to re-render the InstagramPost
component with a new value of likes
.
You can see this if you place a console.log(likes)
statement inside of handleClick
callback.
This kind of makes sense: setLikes
isn't actually changing any value. It's just saying what the next value should be.
Next up we'll make a form for the user to add new pet pictures.
Creating a form using JSX in React is almost identical to creating a form using HTML. Take a look at NewPetForm.jsx
:
Instead of for
we use htmlFor
when connecting labels and inputs.
We use onSubmit
instead of using addEventListener
.
Now, how do we handle the submission event?
A controlled form is a form element whose input values are controlled by React state rather than through DOM manipulation.
To create a controlled form, we will:
Create a piece of state for each input we want to control
Assign the value
prop of the input to the input state value we just created
Assign an onChange
handler to the input that invokes the state setter function
When handling submissions, we can simply reference the input state values.
Remember to reset the state values after submission.
Notice how each input has a value
and an onChange
prop associated with a particular piece of state.
When it is time to submit the form, we can easily use the src
and caption
state values without digging through the form.
The last step to putting this together is having the form submission actually add a new picture to the list of pictures.
Here is the component tree of the application:
The challenge is that PicturesList
is where the pictures
are defined but we want to update the list of pictures from NewPetForm
.
If we were to turn the pictures
array into some state like this:
useState
must be called at the top of a component. .