Back to Blog
Lesson 14 of the React Fundamentals: Build Modern UIs from Scratch course
ReactJune 25, 20263 min read

Managing State with useState: A Beginner’s Guide to React Hooks

Master the useState hook to add interactivity to your React components. Learn how to initialize and update local state to build dynamic user interfaces.

reacthooksuseStatestate managementfrontendjavascript

Previously in this course, we discussed the core concept of introduction to react state: making your ui interactive, which explained why standard JavaScript variables aren't enough to trigger UI updates in React. In this lesson, we’ll move from theory to implementation by mastering the useState hook.

By the end of this lesson, you will be able to import useState, initialize state variables, and trigger re-renders by updating state with setter functions.

Understanding useState from First Principles

In React, a component is a function that returns UI. When data changes, you want that UI to update automatically. However, local variables inside a function are reset every time that function runs. React solves this with hooks, specifically useState.

Think of useState as a "memory slot" that React manages for your component. When you call useState, you provide an initial value. React returns an array with exactly two elements:

  1. The current state value.
  2. A setter function that updates that value and schedules a re-render of your component.

Implementing State in Your Project

Let's add a "Like" button to our MovieCard component. We want to track whether a user has liked a movie.

First, import the hook from React at the top of your file:

JAVASCRIPT
import { useState } from CE9178">'react';

Inside your component, call the hook. We use array destructuring to grab the two values returned by useState:

JAVASCRIPT
function MovieCard({ title }) {
  // Initialize state: CE9178">'isLiked' is the value, CE9178">'setIsLiked' is the updater
  const [isLiked, setIsLiked] = useState(false);

  return (
    <div className="movie-card">
      <h3>{title}</h3>
      <button onClick={() => setIsLiked(!isLiked)}>
        {isLiked ? CE9178">'❤️ Liked' : CE9178">'🤍 Like'}
      </button>
    </div>
  );
}

Breaking Down the Code

  • Initialization: useState(false) tells React that the initial value of isLiked should be false.
  • The Setter: setIsLiked is the only way you should ever change this value. Calling it tells React: "The data changed, please re-run this component function and update the DOM."
  • Re-rendering: Because we updated the state, React calls the MovieCard function again. This time, isLiked holds the new value, and the button text updates accordingly.

Hands-on Exercise: Add a View Counter

In your movie-browser project, locate your MovieCard component. I want you to:

  1. Initialize a new state variable called views starting at 0.
  2. Add a button labeled "View Movie".
  3. Use the setter function inside an onClick handler to increment the views count every time the button is clicked.

Hint: You can use setIsViews(views + 1) inside your event handler.

Common Pitfalls

Even experienced developers trip over these three common issues with useState:

  1. Direct Mutation: Never modify state directly (e.g., isLiked = true). React won't know the value changed, and your UI will remain stale. Always use the setter function.
  2. Calling Hooks Conditionally: You must call useState at the top level of your component. Never place it inside an if statement or a loop. React relies on the order of hooks to keep track of which state belongs to which component.
  3. State Stale-ness: Remember that the setter function is asynchronous. It doesn't update the variable immediately in the current line of code; it schedules an update for the next render. If you need to update state based on its previous value, we will cover the functional update pattern in a later lesson.

Recap

You’ve now moved beyond static markup. By using useState, you allow your components to "remember" data and respond to user interactions. Remember: useState gives you the current value and a setter function. Use the setter to trigger updates, and always keep your hooks at the top level of your functional components.

Up next: We'll dive into react form handling: controlled vs. uncontrolled components to synchronize input fields with state for a professional search experience.

Similar Posts