Falytom logoFALYTOM
Games
ToolsUI ComponentsServicesProductsAbout
LoginSign Up
menu
  1. Home
  2. /Web Development
  3. /React
  4. /Usestate Hook
Your Progress0%
0 of 42 completed

React Topics

Getting Started

  • What is React?
  • React vs Vanilla JavaScript
  • Setting Up Your Environment
  • Your First React App

JSX Fundamentals

  • Introduction to JSX
  • JSX Expressions and Variables
  • Conditional Rendering
  • Lists and Keys
  • Styling in JSX

Components Basics

  • Function Components
  • Props
  • Children Prop
  • Props Destructuring
  • Component Composition

State Management

  • Introduction to State
  • useState Hook
  • State Updates and Re-renders
  • Multiple State Variables
  • State Best Practices

Events and Interactivity

  • Handling Events
  • Event Objects
  • Forms in React
  • Form Validation

Side Effects and Data

  • Introduction to useEffect
  • Data Fetching
  • Cleanup Functions
  • Dependency Arrays

Advanced Hooks

  • useRef Hook
  • useContext Hook
  • useMemo Hook
  • useCallback Hook

React Patterns

  • Custom Hooks
  • Higher-Order Components
  • Render Props Pattern

React Router

  • Introduction to React Router
  • Routes and Navigation
  • Dynamic Routes and Parameters

Best Practices

  • Component Organization
  • Performance Optimization
  • Error Handling
  • Testing React Components

Real World Project

  • Building a Complete App

useState Hook

Adding state to your components

Now that you understand what state is, it's time to learn how to actually use it! The useState hook is React's primary way to add state to function components. It's simple, powerful, and absolutely essential for building interactive UIs. In this lesson, you'll learn how to create state, update it, and handle different data types - making your components truly dynamic and responsive.

Basic useState Syntax

Here's the fundamental pattern for using useState:

basic-syntax.jsx
import React from 'react'

function Counter() {
  // Create state with useState
  const [count, setCount] = React.useState(0)
  //     ↑       ↑                           ↑
  //  current  setter                  initial value
  //   value   function
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  )
}

// When you click the button:
// 1. setCount(count + 1) is called
// 2. React re-renders the component
// 3. count now has the new value
// 4. UI updates to show new count

Breaking Down useState:

  • React.useState(initialValue) - Creates a state variable
  • Returns an array with 2 elements: [value, setter]
  • count - The current state value (read it in your JSX)
  • setCount - Function to update the state
  • 0 - The initial value (only used on first render)

Your First useState Example

Let's build a working counter step by step:

counter.jsx
function Counter() {
  // Step 1: Create state
  const [count, setCount] = React.useState(0)
  
  // Step 2: Create handler function
  const increment = () => {
    setCount(count + 1)  // Update state
  }
  
  const decrement = () => {
    setCount(count - 1)  // Update state
  }
  
  const reset = () => {
    setCount(0)  // Reset to initial value
  }
  
  // Step 3: Use state in JSX
  return (
    <div>
      <h2>Counter: {count}</h2>
      <button onClick={increment}>+1</button>
      <button onClick={decrement}>-1</button>
      <button onClick={reset}>Reset</button>
    </div>
  )
}

💡 Naming Convention

State variables are typically named with a descriptive noun:
count, name, isOpen

Setter functions are named with "set" + capitalized variable name:
setCount, setName, setIsOpen

Different State Types

1. Number State

number-state.jsx
function Counter() {
  const [count, setCount] = React.useState(0)
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
      <button onClick={() => setCount(count * 2)}>×2</button>
      <button onClick={() => setCount(0)}>Reset</button>
    </div>
  )
}

2. String State

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

3. Boolean State

boolean-state.jsx
function Toggle() {
  const [isOn, setIsOn] = React.useState(false)
  
  return (
    <div>
      <p>The light is {isOn ? 'ON' : 'OFF'}</p>
      <button onClick={() => setIsOn(!isOn)}>
        Toggle
      </button>
      <button onClick={() => setIsOn(true)}>
        Turn ON
      </button>
      <button onClick={() => setIsOn(false)}>
        Turn OFF
      </button>
    </div>
  )
}

4. Array State

array-state.jsx
function TodoList() {
  const [todos, setTodos] = React.useState([])
  const [input, setInput] = React.useState('')
  
  const addTodo = () => {
    if (input.trim()) {
      setTodos([...todos, input])  // Add to array
      setInput('')  // Clear input
    }
  }
  
  const removeTodo = (index) => {
    setTodos(todos.filter((_, i) => i !== index))  // Remove from array
  }
  
  return (
    <div>
      <input
        value={input}
        onChange={(e) => setInput(e.target.value)}
        placeholder="Add todo"
      />
      <button onClick={addTodo}>Add</button>
      
      <ul>
        {todos.map((todo, index) => (
          <li key={index}>
            {todo}
            <button onClick={() => removeTodo(index)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  )
}

5. Object State

object-state.jsx
function UserForm() {
  const [user, setUser] = React.useState({
    name: '',
    email: '',
    age: 0
  })
  
  const updateName = (e) => {
    setUser({ ...user, name: e.target.value })
  }
  
  const updateEmail = (e) => {
    setUser({ ...user, email: e.target.value })
  }
  
  const updateAge = (e) => {
    setUser({ ...user, age: parseInt(e.target.value) })
  }
  
  return (
    <div>
      <input
        type="text"
        value={user.name}
        onChange={updateName}
        placeholder="Name"
      />
      <input
        type="email"
        value={user.email}
        onChange={updateEmail}
        placeholder="Email"
      />
      <input
        type="number"
        value={user.age}
        onChange={updateAge}
        placeholder="Age"
      />
      
      <pre>{JSON.stringify(user, null, 2)}</pre>
    </div>
  )
}

Important: State is Immutable!

Never modify state directly:
❌ todos.push(newTodo)
❌ user.name = 'Alice'

Always create a new value:
✅ setTodos([...todos, newTodo])
✅ setUser({ ...user, name: 'Alice' })

Updating State

Direct Value Updates

direct-updates.jsx
function Example() {
  const [count, setCount] = React.useState(0)
  const [name, setName] = React.useState('Alice')
  const [isOpen, setIsOpen] = React.useState(false)
  
  // Direct value - pass the new value
  setCount(5)           // Sets count to 5
  setName('Bob')        // Sets name to 'Bob'
  setIsOpen(true)       // Sets isOpen to true
  
  // Based on current value
  setCount(count + 1)   // Increment count
  setName('')           // Clear name
  setIsOpen(!isOpen)    // Toggle isOpen
}

Function Updates (Recommended for Previous State)

function-updates.jsx
function Counter() {
  const [count, setCount] = React.useState(0)
  
  // ❌ Not reliable for multiple updates
  const increment = () => {
    setCount(count + 1)
    setCount(count + 1)  // Still uses old count!
    setCount(count + 1)  // Still old count!
    // Result: count increases by 1, not 3
  }
  
  // ✅ Reliable - uses previous state
  const increment = () => {
    setCount(prev => prev + 1)  // prev is the actual current value
    setCount(prev => prev + 1)  // prev is now updated
    setCount(prev => prev + 1)  // prev is updated again
    // Result: count increases by 3
  }
  
  return <button onClick={increment}>Count: {count}</button>
}

🎯 When to Use Function Updates

Use function form setState(prev => ...) when:
• The new state depends on the previous state
• You're updating state multiple times
• You're in a loop or async function

Use direct form setState(value) when:
• Setting a completely new value
• The new value doesn't depend on old value

Common useState Patterns

1. Toggle Pattern

toggle-pattern.jsx
function Modal() {
  const [isOpen, setIsOpen] = React.useState(false)
  
  const toggle = () => setIsOpen(!isOpen)
  const open = () => setIsOpen(true)
  const close = () => setIsOpen(false)
  
  return (
    <div>
      <button onClick={open}>Open Modal</button>
      
      {isOpen && (
        <div className="modal">
          <div className="modal-content">
            <h2>Modal Content</h2>
            <button onClick={close}>Close</button>
          </div>
        </div>
      )}
    </div>
  )
}

2. Input Binding Pattern

input-binding.jsx
function SearchBox() {
  const [query, setQuery] = React.useState('')
  
  const handleSearch = () => {
    console.log('Searching for:', query)
  }
  
  return (
    <div>
      <input
        type="text"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search..."
      />
      <button onClick={handleSearch}>Search</button>
      <button onClick={() => setQuery('')}>Clear</button>
    </div>
  )
}

3. Counter Pattern

counter-pattern.jsx
function Counter() {
  const [count, setCount] = React.useState(0)
  
  const increment = () => setCount(prev => prev + 1)
  const decrement = () => setCount(prev => prev - 1)
  const reset = () => setCount(0)
  const incrementBy = (amount) => setCount(prev => prev + amount)
  
  return (
    <div>
      <h2>{count}</h2>
      <button onClick={increment}>+1</button>
      <button onClick={decrement}>-1</button>
      <button onClick={() => incrementBy(5)}>+5</button>
      <button onClick={reset}>Reset</button>
    </div>
  )
}

4. List Management Pattern

list-pattern.jsx
function ItemList() {
  const [items, setItems] = React.useState(['Item 1', 'Item 2'])
  
  const addItem = () => {
    const newItem = `Item ${items.length + 1}`
    setItems([...items, newItem])
  }
  
  const removeItem = (index) => {
    setItems(items.filter((_, i) => i !== index))
  }
  
  const clearAll = () => {
    setItems([])
  }
  
  return (
    <div>
      <button onClick={addItem}>Add Item</button>
      <button onClick={clearAll}>Clear All</button>
      
      <ul>
        {items.map((item, index) => (
          <li key={index}>
            {item}
            <button onClick={() => removeItem(index)}>×</button>
          </li>
        ))}
      </ul>
    </div>
  )
}

5. Form State Pattern

form-pattern.jsx
function LoginForm() {
  const [formData, setFormData] = React.useState({
    email: '',
    password: '',
    rememberMe: false
  })
  
  const handleChange = (e) => {
    const { name, value, type, checked } = e.target
    setFormData({
      ...formData,
      [name]: type === 'checkbox' ? checked : value
    })
  }
  
  const handleSubmit = (e) => {
    e.preventDefault()
    console.log('Form data:', formData)
  }
  
  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        name="email"
        value={formData.email}
        onChange={handleChange}
      />
      <input
        type="password"
        name="password"
        value={formData.password}
        onChange={handleChange}
      />
      <label>
        <input
          type="checkbox"
          name="rememberMe"
          checked={formData.rememberMe}
          onChange={handleChange}
        />
        Remember me
      </label>
      <button type="submit">Login</button>
    </form>
  )
}

Interactive Demo

ReactPlayground.jsx
Code Editor
Preview

💡 Tip: Edit the code above and click "Run" to see your changes

Common useState Mistakes

1. Mutating State Directly

mistake-mutation.jsx
function TodoList() {
  const [todos, setTodos] = React.useState([])
  
  // ❌ Wrong - mutates state
  const addTodo = (text) => {
    todos.push(text)
    setTodos(todos)  // React won't re-render!
  }
  
  // ✅ Correct - creates new array
  const addTodo = (text) => {
    setTodos([...todos, text])
  }
}

2. Using State Immediately After Setting

mistake-immediate.jsx
function Counter() {
  const [count, setCount] = React.useState(0)
  
  // ❌ Wrong - count won't be updated yet
  const handleClick = () => {
    setCount(count + 1)
    console.log(count)  // Still shows old value!
  }
  
  // ✅ Correct - use the value you're setting
  const handleClick = () => {
    const newCount = count + 1
    setCount(newCount)
    console.log(newCount)  // Shows new value
  }
}

3. Calling Setter Function Incorrectly

mistake-setter.jsx
function Example() {
  const [count, setCount] = React.useState(0)
  
  // ❌ Wrong - calling immediately (infinite loop!)
  return <button onClick={setCount(count + 1)}>Click</button>
  
  // ✅ Correct - pass a function
  return <button onClick={() => setCount(count + 1)}>Click</button>
  
  // ✅ Also correct - reference function
  const increment = () => setCount(count + 1)
  return <button onClick={increment}>Click</button>
}

4. Forgetting Dependencies

mistake-dependencies.jsx
function Counter() {
  const [count, setCount] = React.useState(0)
  
  // ❌ Using stale count value
  const incrementTwice = () => {
    setCount(count + 1)
    setCount(count + 1)  // Uses same old count!
    // Result: increments by 1, not 2
  }
  
  // ✅ Use function form for previous state
  const incrementTwice = () => {
    setCount(prev => prev + 1)
    setCount(prev => prev + 1)
    // Result: increments by 2
  }
}

5. Initializing with Expensive Computation

mistake-init.jsx
// ❌ Runs on every render (slow!)
const [data, setData] = React.useState(expensiveCalculation())

// ✅ Only runs once (fast!)
const [data, setData] = React.useState(() => expensiveCalculation())

// The function form ensures it only runs once

Key Takeaways

  • useState(initialValue) creates state in function components
  • Returns array: [value, setter]
  • Setter function triggers re-renders
  • Use setState(newValue) for direct updates
  • Use setState(prev => newValue) when new state depends on previous
  • Never mutate state directly - always create new values
  • State updates are asynchronous
  • Works with any data type: primitives, objects, arrays
  • For objects/arrays, use spread operator to create copies
  • Name state variables descriptively (count, name, isOpen)
  • Name setters with "set" prefix (setCount, setName, setIsOpen)
  • Each component instance has its own state
  • Initial value only used on first render

What's Next?

You now know how to use the useState hook to add state to your components! You can create interactive counters, forms, toggles, and more.

But there's more to understand about how state works. In the next lesson, you'll learn about state updates and re-renders:

  • How React decides when to re-render
  • What happens during a re-render
  • Why state updates are batched
  • How to optimize re-renders
  • Common re-rendering pitfalls

Understanding re-renders will help you write more efficient React applications! 🚀

Learning how to add state to React components with useState!

Previous
Introduction to State
Next
State Updates and Re-renders

Never Miss a New React Tutorial

Join 2,000+ developers learning React step-by-step. Get new tutorials, tips, and exclusive resources delivered to your inbox - completely FREE.

You might also like

UI Components

Ready-made components for your projects

Developer Tools

Boost productivity with handy generators

HTML Game

Learn HTML concepts through interactive gameplay

Join Our Web Development Training Program

Master frontend & backend development with hands-on projects.

React Tutorials

0 of 42 completed

Your Progress0%

Topics

Getting Started

  • What is React?
  • React vs Vanilla JavaScript
  • Setting Up Your Environment
  • Your First React App

JSX Fundamentals

  • Introduction to JSX
  • JSX Expressions and Variables
  • Conditional Rendering
  • Lists and Keys
  • Styling in JSX

Components Basics

  • Function Components
  • Props
  • Children Prop
  • Props Destructuring
  • Component Composition

State Management

  • Introduction to State
  • useState Hook
  • State Updates and Re-renders
  • Multiple State Variables
  • State Best Practices

Events and Interactivity

  • Handling Events
  • Event Objects
  • Forms in React
  • Form Validation

Side Effects and Data

  • Introduction to useEffect
  • Data Fetching
  • Cleanup Functions
  • Dependency Arrays

Advanced Hooks

  • useRef Hook
  • useContext Hook
  • useMemo Hook
  • useCallback Hook

React Patterns

  • Custom Hooks
  • Higher-Order Components
  • Render Props Pattern

React Router

  • Introduction to React Router
  • Routes and Navigation
  • Dynamic Routes and Parameters

Best Practices

  • Component Organization
  • Performance Optimization
  • Error Handling
  • Testing React Components

Real World Project

  • Building a Complete App
Falytom logoFALYTOM

Learn technologies like HTML, CSS, JavaScript, React, NodeJS and more through interactive games, tutorials, components and free tools. Transform your businesses with AI chatbots, SEO-optimized websites, and professional development services.

© 2025 Tomilola Group
  • Facebook logo
  • Twitter logo
  • Instagram logo
  • LinkedIn logo
  • GitHub logo
  • YouTube logo