useState in React

Mastering useState in React — With Real Examples

In post-1 of this series we introduced to React hooks. The useState hook is the foundation of React Hooks, allowing functional components to hold and update state. In this tutorial, we’ll explore how useState works, cover common mistakes to avoid, and enhance our Task Tracker App so users can dynamically add tasks. If you’re new to hooks, this is the perfect place to start building interactivity.

So, follow along as we dive deeper in the world of React!

What is useState in React?

The useState hook lets you add state to functional components.

State is simply data that changes over time — like a counter value, form input, or a list of tasks.

With useState, React knows when to re-render your component whenever state changes.

What You’ll Learn in This Post

  • How to update state correctly (including objects and arrays)
  • Common mistakes beginners make with useState
  • Adding tasks dynamically to our Task Tracker App

Syntax of useState

const [state, setState] = useState(initialValue);
  • state → current value of your state variable
  • setState → function to update the state
  • initialValue → the starting value of the state

Example 1: Counter with useState

import React, { useState } from "react";
function Counter() {
  const [count, setCount] = useState(0); // initial state = 0
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

export default Counter;

When you click the button, React updates the state and re-renders the component.

Common Mistakes with useState

1. Updating state directly (don’t do this):

const [count, setCount] = useState(0);
count = count + 1; // ❌ Wrong

2. Correct way (use setter function):

setCount(count + 1);

3. Updating arrays/objects — always use a copy (spread operator):

// Array example
setTasks([...tasks, newTask]);

// Object example
setUser({ ...user, name: "John" });

Mini Project Step: Dynamic Task List with useState

Now let’s bring useState into our Task Tracker App.

1. Add state for tasks

import React, { useState } from "react";

function App() {
  const [tasks, setTasks] = useState([
    { id: 1, text: "Learn React Hooks" },
    { id: 2, text: "Build a Task Tracker App" },
    { id: 3, text: "Master useState and useEffect" }
  ]);
  return (
    <div style={{ padding: "20px" }}>
      <h1>Task Tracker</h1>
      <ul>
        {tasks.map(task => (
          <li key={task.id}>{task.text}</li>
        ))}
      </ul>
    </div>
  );
}
export default App;

Now the tasks are inside React state — ready to be updated dynamically.

2. Add a form to create new tasks

import React, { useState } from "react";
function App() {
  const [tasks, setTasks] = useState([
    { id: 1, text: "Learn React Hooks" },
    { id: 2, text: "Build a Task Tracker App" }
  ]);
  const [newTask, setNewTask] = useState("");

  const addTask = (e) => {
    e.preventDefault();
    if (!newTask.trim()) return;

    const task = { id: Date.now(), text: newTask };
    setTasks([...tasks, task]); // update state
    setNewTask(""); // clear input
  };
  return (
    <div style={{ padding: "20px" }}>
      <h1>Task Tracker</h1>

      {/* Form to add tasks */}
      <form onSubmit={addTask}>
        <input
          type="text"
          placeholder="Enter new task"
          value={newTask}
          onChange={(e) => setNewTask(e.target.value)}
        />
        <button type="submit">Add Task</button>
      </form>

      {/* Render task list */}
      <ul>
        {tasks.map(task => (
          <li key={task.id}>{task.text}</li>
        ))}
      </ul>
    </div>
  );
}
export default App;

Now you can add tasks dynamically!

What We’ve Achieved

  • Learned the basics of useState
  • Avoided common mistakes with state updates
  • Updated our Task Tracker App to let users add new tasks

Learning Path

Post 1: Introduction to React Hooks (Why They Matter + Starter Project) – Post-1

Learn what hooks are, why they replaced class components, and set up the starter Task Tracker App.

Post 2: Mastering useState in React – Current Post

Manage state in functional components. Add new tasks dynamically with useState.

Post 3: Understanding useEffect (Side Effects + API Calls) – Read Post 3

Fetch tasks from an API, mimic lifecycle methods, and clean up side effects.

Post 4: Using useRef in React (Not Just for DOM Access) – Read Post 4

Control focus on the input field and learn how to store values without re-renders.

Post 5: Creating Custom Hooks (useLocalStorage) – Read Post 5

Extract reusable logic into a custom hook that persists tasks across refreshes.

Post 6: Optimizing Performance with useMemo and useCallbackRead Post 6

Add a search feature and optimize it with memoization to prevent unnecessary re-renders.

Post 7 (Final): Building a Complete Task Tracker with React Hooks – Read Post 7

Add delete + toggle complete functionality, and wrap up with a fully functional app.


Discover more from TACETRA

Subscribe to get the latest posts sent to your email.

Let's have a discussion!

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from TACETRA

Subscribe now to keep reading and get access to the full archive.

Continue reading