Skip to main content
React Introduction
CHAPTER 12 Beginner

React useState Hook

Updated: May 13, 2026
20 min read

# React useState Hook

1. Introduction

We've used useState in previous chapters to build basic interactivity. However, mastering useState is what separates beginners from intermediate React developers. In this chapter, we will explore the rules of Hooks, how to update state based on previous state, and how to work with complex state types like objects and arrays.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand the strict rules for calling React Hooks.
  • Update state safely using the "functional update" pattern.
  • Update nested objects and arrays in state without mutating them.

3. Beginner-Friendly Explanations

What is a Hook?

Before 2018, Functional Components were "dumb" or "stateless". They couldn't remember anything. React introduced "Hooks" to allow these functions to "hook into" React features like state and lifecycle. Any function starting with use (like useState, useEffect) is a hook.

The Rules of Hooks

  1. 1. Only call hooks at the top level: You CANNOT put a hook inside an if statement, a for loop, or a nested function. They must be at the very top of your component function.
  1. 2. Only call hooks from React components: You cannot call useState inside a regular JavaScript file or a standard helper function.

4. Syntax Explanation & Advanced Patterns

Pattern 1: Functional Updates

If your new state depends on your old state (e.g., adding 1 to a counter), you should use a "functional update" instead of passing a direct value. Why? Because React batches state updates for performance. If you click a button very fast, React might not have finished the first update before you start the second, leading to incorrect calculations.

```jsx id="ch12_ex1" // Example React component import { useState } from 'react';

function SafeCounter() { const [count, setCount] = useState(0);

const incrementByTwo = () => { // ❌ Risky: Relies on the state variable directly // setCount(count + 1); // setCount(count + 1); // This might not equal 2!

// ✅ Safe: Uses functional update. React guarantees 'prevCount' is the most recent value. setCount(prevCount => prevCount + 1); setCount(prevCount => prevCount + 1); // This WILL equal 2! };

return <button onClick={incrementByTwo}>Count is {count}</button>; }

123
### Pattern 2: State with Objects
When your state is an object, calling `setMyObject` does **not** merge the new data with the old data. It completely overwrites it. You must use the "spread operator" (`...`) to manually copy the old data.

jsx id="ch12_ex2" // Example React component function ProfileEditor() { const [user, setUser] = useState({ name: "Alex", age: 25, city: "NY" });

const updateCity = () => { // ❌ Wrong: Deletes name and age! // setUser({ city: "LA" });

// ✅ Right: Copy old user data, THEN overwrite city. setUser({ ...user, city: "LA" }); };

return <button onClick={updateCity}>Move to LA</button>; }

123
### Pattern 3: State with Arrays
Just like objects, you cannot mutate state arrays directly using methods like `.push()`. You must create a new array.

jsx id="ch12_ex3" // Example React component function ShoppingList() { const [items, setItems] = useState(["Apple", "Banana"]);

const addItem = () => { // ❌ Wrong: Mutates the existing array in memory. React won't re-render! // items.push("Orange"); // setItems(items);

// ✅ Right: Create a NEW array. Spread the old items, add the new one. setItems([...items, "Orange"]); };

return <button onClick={addItem}>Add Orange</button>; }

123456789101112131415161718192021
## 5. Output Explanations
React requires **immutability**. It checks if data changed by looking at memory addresses. If you push to an array, the memory address is the same, so React thinks nothing changed. By using `[...oldArray, newItem]`, you create a brand new array in memory, forcing React to re-render.

## 6. Real-World Examples
- **Objects:** User profiles, form data, application settings.
- **Arrays:** Lists of comments, shopping carts, task lists.

## 7. Common Mistakes
- **Mutating objects/arrays:** Writing `user.age = 26; setUser(user);`. It will cause bugs. Always treat state as strictly read-only and use spread operators.
- **Calling hooks conditionally:** `if (isLoggedIn) { const [user, setUser] = useState() }` will crash React.

## 8. Best Practices
- Break complex objects into multiple `useState` variables if the pieces of data change independently. (e.g., instead of one massive `user` object, maybe have `[name, setName]` and `[settings, setSettings]`).

## 9. Exercises
1. Create a state array containing `[1, 2, 3]`.
2. Write a function that uses the spread operator to add the number `4` to the end of the array.

## 10. Mini Project: Theme Toggle App
Let's build an app that manages a complex settings object in state.

jsx id="ch12_proj1" // Example React component import React, { useState } from 'react';

export default function SettingsDashboard() { // Complex state object const [settings, setSettings] = useState({ theme: 'light', notificationsEnabled: true, volume: 80 });

const toggleTheme = () => { setSettings(prev => ({ ...prev, // Copy other settings theme: prev.theme === 'light' ? 'dark' : 'light' // Toggle theme })); };

const toggleNotifications = () => { setSettings(prev => ({ ...prev, notificationsEnabled: !prev.notificationsEnabled })); };

return ( <div className={min-h-screen p-8 transition-colors duration-500 ${settings.theme === 'dark' ? 'bg-gray-900 text-white' : 'bg-gray-100 text-gray-900'}}> <div className={max-w-md mx-auto p-6 rounded-xl shadow-lg ${settings.theme === 'dark' ? 'bg-gray-800' : 'bg-white'}}> <h1 className="text-2xl font-bold mb-6">User Settings</h1> <div className="space-y-4"> <div className="flex justify-between items-center"> <span>Dark Mode</span> <button onClick={toggleTheme} className={px-4 py-2 rounded-full font-medium ${settings.theme === 'dark' ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-800'}} > {settings.theme === 'dark' ? 'ON' : 'OFF'} </button> </div>

<div className="flex justify-between items-center"> <span>Notifications</span> <button onClick={toggleNotifications} className={px-4 py-2 rounded-full font-medium ${settings.notificationsEnabled ? 'bg-green-500 text-white' : 'bg-gray-200 text-gray-800'}} > {settings.notificationsEnabled ? 'ENABLED' : 'DISABLED'} </button> </div> </div> </div> </div> ); } ``

11. Coding Challenges

Challenge 1: Create an app with an array of strings in state. Add an input field and a submit button. When submitted, use the spread operator to add the input text to the array and display it as a list.

12. MCQs with Answers

Q1: What happens if you call a Hook inside an
if statement? A) It works normally. B) React throws a fatal error because Hooks must be called in the exact same order on every render. C) The state becomes read-only. *Answer: B*

Q2: Which code correctly updates an array in state? A) myArray.push(newItem); setMyArray(myArray); B) setMyArray([...myArray, newItem]); C) setMyArray(myArray + newItem); *Answer: B*

13. Interview Questions

  • Q: Explain why we shouldn't mutate state directly in React.
  • Q: What is the "Rules of Hooks"?

14. FAQs

Can I initialize state with a function? Yes. If your initial state requires heavy computation (like parsing local storage), you can do
useState(() => heavyFunction()). This ensures the heavy function only runs on the first render, not every time the component updates.

15. Summary

The
useState hook is incredibly powerful, but it requires strict adherence to immutability. By using functional updates (prev => prev + 1`) and the spread operator for arrays and objects, you ensure that React always recognizes your state changes and updates the UI reliably.

16. Next Chapter Recommendation

State is great for internal memory, but how do we interact with the outside world? How do we fetch data from a server or set up a timer? In Chapter 13: React useEffect Hook, we will learn how to handle "Side Effects".

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·