Data is constantly changing inside your application. For example, clicking Next on an image carousel should change which image is displayed, selecting an item from a dropdown menu should filter the content, toggling a switch should enable/disable a feature, clicking the Add button on a counter should increment the displayed number.
1export default function Counter() {
2 let count = 0;
3 return (
4 <div>
5 <p>Count: {count}</p>
6 <button
7 onClick={() => {
8 count = count + 1;
9 }}>
10 Add
11 </button>
12 </div>
13 );
14}
For demonstration purposes, this is a counter app. At first, a variable count
is initialized, and every time the Add button is clicked, count
will increment by 1. The logic seems to be correct, but try this demo yourself and you'll find that it doesn't really work.
There are two problems preventing count
to be updated. First of all, changes to local variables won't trigger rerenders. Event though the value of count
is updated when the button is clicked, it will not be displayed.
And second, even if a new render is triggered, local variables don't persist between renders. A new count
variable will be created, and React won't be able to remember its previous value.
State is our solution to this conundrum. It is a way for React to remember certain things, and also triggers a rerender when the stored information changes.
Introducing useState, the first React hook
To create states, instead of defining the variable directly, you must use a function called useState()
.
1import { useState } from "react";
2
3export default function Counter() {
4 const [count, setCount] = useState(0);
5 return (
6 . . .
7 );
8}
useState()
is called a hook in React, and in this case, the hook returns two values, count
and setCount
. count
is the state variable and setCount
is a setter function for count
. useState(0)
tells React that the initial value of count
is 0.