State and Events

Introduction

In the previous lesson, you learned how React uses components and props to make your UI modular and reusable. Now, we’ll take the next big step — making those components interactive.

In any dynamic application, data changes — users click buttons, type in forms, open menus, or update settings.

To handle these interactions, React gives us two powerful tools:

  • State – to manage changing data

  • Events – to handle user actions like clicks, typing, and submissions

By mastering these two concepts, you’ll unlock the ability to create responsive, real-world applications.

What Is State?

State is a built-in React feature that lets components keep track of changing data. While props are data passed into a component, state is data that belongs to a component itself.

When state changes, React automatically re-renders the component — showing the latest data on the screen without manually updating the DOM.

Example:

import { useState } from "react";

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

  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={() => setCount(count + 1)}>Increase</button>
    </div>
  );
}

How It Works:

  • useState(0) creates a state variable count and initializes it to 0.

  • setCount is the function used to update count.

  • Every time setCount runs, React re-renders the component with the new value.

The number on the screen updates automatically without manual refresh.

The useState Hook Explained

The useState hook always returns two values:

The current state value.
A function to update it.

Syntax:

const [state, setState] = useState(initialValue);

You can use any data type for state:

  • String ? useState("Hello")

  • Number ? useState(0)

  • Boolean ? useState(false)

  • Array ? useState([])

  • Object ? useState({})

Example with multiple data types:

function Example() {
  const [name, setName] = useState("Alex");
  const [age, setAge] = useState(25);
  const [isOnline, setIsOnline] = useState(true);

  return (
    <div>
      <h3>{name} ({age})</h3>
      <p>Status: {isOnline ? "Online" : "Offline"}</p>
    </div>
  );
}

You can have multiple state variables in one component, and each one works independently.

Handling User Events

React handles events similarly to regular HTML but with a few key differences:

Event names are camelCase (for example, onClick, not onclick).

Event handlers are passed as functions, not strings.

Example:

function ClickMe() {
  function handleClick() {
    alert("Button clicked!");
  }

  return <button onClick={handleClick}>Click Me</button>;
}

Inline arrow function example:

<button onClick={() => alert("Clicked!")}>Click</button>

Updating State with Events

You can update state inside an event handler.

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

  function increment() {
    setCount(count + 1);
  }

  return (
    <div>
      <h3>Count: {count}</h3>
      <button onClick={increment}>Add +1</button>
    </div>
  );
}

Every time the button is clicked, the state updates and React re-renders the component.

If you need to base your update on the previous state, use the function form:

setCount((prevCount) => prevCount + 1);

Managing Complex State (Objects and Arrays)

State can hold objects or arrays.

function UserProfile() {
  const [user, setUser] = useState({ name: "John", age: 25 });

  function increaseAge() {
    setUser({ ...user, age: user.age + 1 });
  }

  return (
    <div>
      <h3>{user.name} ({user.age})</h3>
      <button onClick={increaseAge}>Increase Age</button>
    </div>
  );
}

The spread operator copies the existing object and updates only the required property. Always treat state as immutable.

Event Handling with Parameters

function GreetUser() {
  const greet = (name) => alert(`Hello, ${name}!`);

  return (
    <div>
      <button onClick={() => greet("Ava")}>Greet Ava</button>
      <button onClick={() => greet("Liam")}>Greet Liam</button>
    </div>
  );
}

Arrow functions allow passing parameters safely.

Controlled Components (Forms and Inputs)

function FormExample() {
  const [name, setName] = useState("");

  function handleChange(e) {
    setName(e.target.value);
  }

  function handleSubmit(e) {
    e.preventDefault();
    alert(`Hello, ${name}!`);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" value={name} onChange={handleChange} placeholder="Enter name" />
      <button type="submit">Submit</button>
    </form>
  );
}

The input’s value is controlled by state. When the user types, the state updates and the UI reflects the latest value.

Real-Life Example: Simple Todo List

import { useState } from "react";

function TodoApp() {
  const [task, setTask] = useState("");
  const [tasks, setTasks] = useState([]);

  function addTask(e) {
    e.preventDefault();
    if (task.trim()) {
      setTasks([...tasks, task]);
      setTask("");
    }
  }

  return (
    <div>
      <h2>My Todo List</h2>
      <form onSubmit={addTask}>
        <input
          type="text"
          value={task}
          onChange={(e) => setTask(e.target.value)}
          placeholder="Enter a task"
        />
        <button type="submit">Add</button>
      </form>

      <ul>
        {tasks.map((t, index) => (
          <li key={index}>{t}</li>
        ))}
      </ul>
    </div>
  );
}

The user types a task, submits the form, and the list updates instantly.

Common Mistakes to Avoid

  • Updating state directly (count++) – Doesn’t trigger re-render – Use setCount(count + 1)

  • Forgetting to call the state updater – Value never changes – Always call the setter function

  • Missing e.preventDefault() in forms – Page reloads on submit – Prevent form default behavior

  • Using stale state in updater – Multiple updates may conflict – Use setState(prev => prev + 1)

  • Mutating arrays or objects directly – React won’t detect change – Use the spread operator

Summary

In this lesson, you learned what a state is and how it differs from props, how to use the useState hook, how events handle user interactions, how to build controlled components, and best practices for updating complex state. With state and events, your components become interactive and dynamic.