All posts
ReactAugust 24, 20267 min read

React useState Hook for Beginners: A Simple Guide

Learn the React useState hook for beginners with simple, line-by-line examples. Understand state, re-renders, and how to build your first interactive component.

F
Fepiq Team
Fepiq

Searching for "react usestate hook for beginners"? Here is the short answer: useState is a built-in React function that lets a component remember a value and update the screen automatically when that value changes. This guide explains exactly how it works, with small, copy-pasteable examples you can run today, even if you have never used a React hook before.

What Is useState in React?

In plain JavaScript, a normal variable forgets its value every time a function runs again. A React component is just a JavaScript function, and it re-runs every time something changes on the screen. So if you stored a number in a normal variable, it would reset to its starting value on every re-render. useState solves this problem. It gives your component a piece of memory, called state, that survives between re-renders and tells React to redraw the screen whenever that memory changes.

Why Do You Need State At All?

React components receive data two ways: props, which come from a parent component and never change inside the child, and state, which a component owns and controls itself. If you have not compared the two yet, our earlier guide covers the difference in detail before you continue here.

Not sure how state is different from props? Read our beginner comparison first.

Read: React Props vs State Explained

The useState Syntax, Piece by Piece

Before building anything, look at the single line of code you will write every time you use this hook:

jsx
import { useState } from "react";

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

Line 1 imports useState from the react package, so React knows you want to use it. Line 3 calls useState(0), which sets the starting value to 0. useState always returns an array with exactly two items: the current value (count) and a function to change it (setCount). The square brackets on the left are JavaScript array destructuring, a shorthand for pulling both items out in one line. You can name these two items anything you like, but the pattern "thing" and "setThing" is the common convention in React code.

Example: A Simple Counter Component

Here is a complete, working component that uses useState to count button clicks:

jsx
import { useState } from "react";

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

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

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={handleClick}>Click me</button>
    </div>
  );
}

export default Counter;

Line 4 creates the state, starting count at 0. Lines 6 to 8 define a function that runs when the button is clicked; it calls setCount with the new value, count + 1. Line 12 shows the current count inside the JSX, using curly braces to insert a JavaScript value into the markup. Line 13 attaches handleClick to the button's onClick event. Every time you click, setCount runs, React updates its memory of count, and the component re-renders with the new number on screen. You never edit the page directly; you just update state, and React handles the redraw.

A Common Mistake: Using count Directly

Beginners sometimes try count = count + 1 instead of calling setCount. This will not work. Changing a state variable directly does not tell React to re-render, so the screen never updates. Always change state through its setter function, here setCount.

Example: Controlling a Text Input

useState is also how you read what a user types into a form. This pattern is called a controlled input, because React state controls the input's value:

jsx
import { useState } from "react";

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

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

  return (
    <div>
      <input value={name} onChange={handleChange} />
      <p>Hello, {name || "stranger"}!</p>
    </div>
  );
}

export default NameForm;

Line 4 starts name as an empty string. Line 6 defines handleChange, which runs on every keystroke; event.target.value is the text currently inside the input box. Line 11 sets the input's value to the name state, and attaches handleChange to its onChange event. Line 12 greets the user with what they typed, falling back to "stranger" if name is still empty. Because the input's value always comes from state, React and the screen never disagree about what the box contains.

useState vs a Regular Variable

Regular variable (let x = 0)State (useState(0))
Resets every time the component re-runsKeeps its value between re-renders
Changing it does not update the screenChanging it (via the setter) redraws the screen
Fine for values used only inside one function callNeeded for anything the user should see change

Common Mistakes Beginners Make with useState

  • Forgetting to import useState from react before calling it.
  • Updating a variable directly instead of calling its setter function, so the screen never changes.
  • Calling useState inside an if statement or a loop; hooks must always run in the same order, so only call them at the top level of a component.
  • Storing values in state that could just be calculated from other state or props, which adds unnecessary complexity.
  • Expecting the state variable to update immediately after calling the setter; React schedules the update and re-renders shortly after, not instantly mid-function.

Practice: Build a Show/Hide Toggle

Try building this yourself before checking the answer below: a button that shows or hides a paragraph of text. You will need a boolean state, true or false, and a setter that flips it.

jsx
import { useState } from "react";

function Toggle() {
  const [isVisible, setIsVisible] = useState(false);

  return (
    <div>
      <button onClick={() => setIsVisible(!isVisible)}>
        {isVisible ? "Hide" : "Show"} details
      </button>
      {isVisible && <p>Here are the details you were looking for.</p>}
    </div>
  );
}

export default Toggle;

Line 4 starts isVisible as false, so the details are hidden at first. Line 8 flips the value with !isVisible, which turns true into false and false into true. Line 9 changes the button label based on the current state. Line 11 uses the && operator: if isVisible is true, the paragraph after && is shown; if it is false, nothing is rendered. This is a very common pattern for showing and hiding content in React.

Frequently asked questions

What does useState actually do in React?+

useState gives a function component a piece of memory called state. It returns the current value and a function to update it, and calling that function tells React to re-render the component with the new value on screen.

Why do I have to call useState instead of just using a normal variable?+

A normal variable resets every time the component function runs again, and changing it does not tell React to update the screen. State persists between re-renders and automatically triggers a redraw when you call its setter function.

Can I use useState more than once in the same component?+

Yes. You can call useState as many times as you need, once for each independent piece of state, such as const [name, setName] = useState('') and const [age, setAge] = useState(0) in the same component.

Why didn't my state update immediately after I called the setter?+

React batches state updates and re-renders shortly after you call the setter, not instantly inside the same line of code. If you log the state variable right after calling its setter, you will often still see the old value; the new value appears on the next render.

What is the difference between useState and props?+

Props are values passed down from a parent component and cannot be changed by the child. State is owned by the component itself and can be updated with its setter function, which is what causes the component to re-render.

Want a team that already knows React inside and out to build your product?

Talk to Fepiq

Get new posts in your inbox

Occasional, no-fluff notes on shipping modern software — startups, automation, Laravel, Shopify and more. No spam, unsubscribe anytime.

Keep reading

Related posts

All posts

Let's build something

Ready to ship your next product with Fepiq?

Book a free discovery call. We'll listen, ask sharp questions, and send you a proposal within 3 business days.