State is a way for React to remember a variable between renders, and when a state is updated, a new render will be registered.
Component with multiple states
In practice, things are usually more complicated. First of all, a component may need to work with multiple states. For example, let's add a theme switcher for our counter app:
1export default function App() {
2 const [count, setCount] = useState(0);
3
4 const [theme, setTheme] = useState("light");
5
6 function handleCountAdd() {
7 setCount(count + 1);
8 }
9
10 function handleThemeSwitch() {
11 theme === "light" ? setTheme("dark") : setTheme("light");
12 }
13
14 return (
15 <div
16 className={
17 theme === "light"
18 ? "border rounded-md p-4 m-4"
19 : "border rounded-md p-4 m-4 bg-gray-900 text-gray-100"
20 }>
21 <button onClick={handleThemeSwitch}>Switch Theme</button>
22
23 <p>Count: {count}</p>
24 <button onClick={handleCountAdd}>Add</button>
25 </div>
26 );
27}
In this example, count
remembers the counter value, and theme
remembers the theme. The event handler handleCountAdd()
updates count
, and handleThemeSwitch()
updates theme
.
Now, consider a more interesting scenario. What happens when a event handler function updates both states at the same time? For example, this counter counts how many times the theme has been toggled.
1export default function App() {
2 const [count, setCount] = useState(0);
3
4 const [theme, setTheme] = useState("light");
5
6 function handleThemeSwitch() {
7 theme === "light" ? setTheme("dark") : setTheme("light");
8 setCount(count + 1);
9 }
10
11 return (
12 <div
13 className={
14 theme === "light"
15 ? "border rounded-md p-4 m-4"
16 : "border rounded-md p-4 m-4 bg-gray-900 text-gray-100"
17 }>
18 <button onClick={handleThemeSwitch}>Switch Theme</button>
19
20 <p>Count: {count}</p>
21 </div>
22 );
23}
We discussed that when a state setter function is executed, the component will be rerendered. But in fact, this new render does not happen immediately.
When a state is updated, a rerender will be registered but not executed immediately. React will wait until the entire event handler function has been executed before triggering the new render. For instance, in the above example, when the event handler is triggered, React will wait until both setter functions to finish before rerender, allowing both states to be updated.
This example then leads to another interesting question, what happens when you update the same state multiple times in the event handler?