React useState Hook

Managing state in functional components

📊 What is useState?

useState is a React Hook that lets you add state to functional components. It returns an array with the current state value and a function to update it, making state management simple and intuitive.


import { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);
  
  return <p>Count: {count}</p>;
}
                                    

useState Key Concepts

🎯

Initial State

Set starting value for state

const [count, setCount] = useState(0);
🔄

State Update

Change state with setter function

setCount(count + 1);
📦

Multiple States

Use multiple useState hooks

const [name, setName] = useState('');
const [age, setAge] = useState(0);
🎨

Any Data Type

Store strings, numbers, objects, arrays

const [user, setUser] = useState({});

🔹 Basic useState Example

The simplest use of useState is to manage a single value like a counter. The hook returns the current value and a function to update it.

import { useState } from 'react';

function Counter() {
  // Declare state variable 'count' with initial value 0
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Output:

You clicked 0 times

🔹 useState with Strings

You can use useState to manage text input values. This is commonly used for forms where users type information like names or messages.

import { useState } from 'react';

function NameInput() {
  const [name, setName] = useState('');
  
  return (
    <div>
      <input 
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Enter your name"
      />
      <p>Hello, {name || 'stranger'}!</p>
    </div>
  );
}

Output:

Hello, stranger!

🔹 useState with Objects

When managing multiple related values, you can store them in an object. Remember to spread the previous state when updating to avoid losing other properties.

import { useState } from 'react';

function UserForm() {
  const [user, setUser] = useState({
    name: '',
    email: '',
    age: 0
  });
  
  const updateName = (e) => {
    setUser({ ...user, name: e.target.value });
  };
  
  return (
    <div>
      <input 
        value={user.name}
        onChange={updateName}
        placeholder="Name"
      />
      <p>Name: {user.name}</p>
    </div>
  );
}

Output:

Name:

🔹 useState with Arrays

Arrays are perfect for managing lists of items. You can add, remove, or update items using array methods combined with the state setter function.

import { useState } from 'react';

function TodoList() {
  const [todos, setTodos] = useState(['Learn React', 'Build app']);
  const [input, setInput] = useState('');
  
  const addTodo = () => {
    if (input.trim()) {
      setTodos([...todos, input]);
      setInput('');
    }
  };
  
  return (
    <div>
      <input 
        value={input}
        onChange={(e) => setInput(e.target.value)}
        placeholder="New todo"
      />
      <button onClick={addTodo}>Add</button>
      <ul>
        {todos.map((todo, index) => (
          <li key={index}>{todo}</li>
        ))}
      </ul>
    </div>
  );
}

Output:

  • Learn React
  • Build app

🔹 Functional Updates

When the new state depends on the previous state, use a function inside the setter. This ensures you always work with the latest state value, especially important for rapid updates.

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  
  // ❌ Not recommended for dependent updates
  const incrementBad = () => {
    setCount(count + 1);
  };
  
  // ✅ Recommended - uses previous state
  const incrementGood = () => {
    setCount(prevCount => prevCount + 1);
  };
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={incrementGood}>
        Increment
      </button>
    </div>
  );
}

Output:

Count: 0

🔹 useState Best Practices

✅ Do's:

  • Descriptive names: Use clear names like [isLoading, setIsLoading]
  • Functional updates: Use prevState when new state depends on old
  • Split state: Use multiple useState for unrelated data
  • Initialize properly: Set appropriate initial values

❌ Don'ts:

  • Don't mutate state: Always create new objects/arrays
  • Don't call in loops: Keep useState at component top level
  • Don't overuse objects: Split into multiple states when possible

🧠 Test Your Knowledge

What does useState return?