Tutorials Logic, IN +91 8092939553 info@tutorialslogic.com
FAQs Support
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Interview Questions Website Development
Compiler Tutorials

React State — useState

What is State?

State is data that a component owns and can change over time. When state changes, React automatically re-renders the component to reflect the new data. State is the mechanism that makes React UIs interactive.

The useState hook is the primary way to add state to function components. It returns a pair: the current state value and a function to update it.

useState — Counter, Toggle, Form Input
import { useState } from 'react'

// Basic counter
function Counter() {
    // useState(initialValue) returns [currentValue, setterFunction]
    const [count, setCount] = useState(0)

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={() => setCount(count + 1)}>+</button>
            <button onClick={() => setCount(count - 1)}>-</button>
            <button onClick={() => setCount(0)}>Reset</button>
        </div>
    )
}

// Functional update — use when new state depends on old state
function SafeCounter() {
    const [count, setCount] = useState(0)

    // WRONG — may use stale state in async contexts:
    // setCount(count + 1)

    // CORRECT — always gets latest state:
    const increment = () => setCount(prev => prev + 1)
    const decrement = () => setCount(prev => prev - 1)

    return (
        <div>
            <p>{count}</p>
            <button onClick={increment}>+</button>
            <button onClick={decrement}>-</button>
        </div>
    )
}

// Toggle state
function Toggle() {
    const [isOn, setIsOn] = useState(false)
    return (
        <button onClick={() => setIsOn(prev => !prev)}>
            {isOn ? 'ON' : 'OFF'}
        </button>
    )
}

// Multiple state variables
function Form() {
    const [name, setName] = useState('')
    const [email, setEmail] = useState('')
    const [age, setAge] = useState(0)

    return (
        <form>
            <input value={name}  onChange={e => setName(e.target.value)}  placeholder="Name" />
            <input value={email} onChange={e => setEmail(e.target.value)} placeholder="Email" />
            <input value={age}   onChange={e => setAge(Number(e.target.value))} type="number" />
        </form>
    )
}
import { useState } from 'react'

// Object state — MUST spread to update
function UserForm() {
    const [user, setUser] = useState({
        name: '',
        email: '',
        role: 'user'
    })

    // WRONG — mutates state directly:
    // user.name = 'Alice'  // React won't re-render!

    // CORRECT — create new object with spread:
    const updateField = (field, value) => {
        setUser(prev => ({ ...prev, [field]: value }))
    }

    return (
        <form>
            <input
                value={user.name}
                onChange={e => updateField('name', e.target.value)}
                placeholder="Name"
            />
            <input
                value={user.email}
                onChange={e => updateField('email', e.target.value)}
                placeholder="Email"
            />
            <select
                value={user.role}
                onChange={e => updateField('role', e.target.value)}
            >
                <option value="user">User</option>
                <option value="admin">Admin</option>
            </select>
            <pre>{JSON.stringify(user, null, 2)}</pre>
        </form>
    )
}
import { useState } from 'react'

// Array state — MUST use non-mutating methods
function TodoList() {
    const [todos, setTodos] = useState([
        { id: 1, text: 'Learn React', done: false },
        { id: 2, text: 'Build a project', done: false },
    ])
    const [input, setInput] = useState('')

    // Add item
    const addTodo = () => {
        if (!input.trim()) return
        setTodos(prev => [
            ...prev,
            { id: Date.now(), text: input, done: false }
        ])
        setInput('')
    }

    // Toggle done
    const toggleTodo = (id) => {
        setTodos(prev =>
            prev.map(todo =>
                todo.id === id ? { ...todo, done: !todo.done } : todo
            )
        )
    }

    // Delete item
    const deleteTodo = (id) => {
        setTodos(prev => prev.filter(todo => todo.id !== id))
    }

    return (
        <div>
            <div>
                <input value={input} onChange={e => setInput(e.target.value)} />
                <button onClick={addTodo}>Add</button>
            </div>
            <ul>
                {todos.map(todo => (
                    <li key={todo.id} style={{ textDecoration: todo.done ? 'line-through' : 'none' }}>
                        <span onClick={() => toggleTodo(todo.id)}>{todo.text}</span>
                        <button onClick={() => deleteTodo(todo.id)}>✕</button>
                    </li>
                ))}
            </ul>
            <p>{todos.filter(t => t.done).length} / {todos.length} done</p>
        </div>
    )
}

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.