Skip to content

React Tutorial State and Events

Understanding State in React

Lesson 43 of 156 2 min read By Deepak Paswan Updated Oct 10, 2026

Runnable lesson · press Try it on the examples to edit and run them here.

A component that only shows its props is like a printed page: it cannot change. To build interfaces that respond to clicks, typing and data, a component needs memory. In React that memory is called state.

Why a normal variable is not enough

Let us try the obvious approach and see why it fails. Press the button in this example and watch both the console and the screen.

App.jsx
JSX
function App() {
  let count = 0;

  function handleClick() {
    count = count + 1;
    console.log("count is now", count);
  }

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Add</button>
    </div>
  );
}

The console shows count is now 1, 2, 3… but the screen says Count: 0 forever. There are two problems:

  1. Changing a local variable does not make React redraw the screen. React only runs your component again when it is told something changed.
  2. Even if it did re-render, count would be reset to 0. Local variables are created fresh every time the function runs, so they do not remember anything between renders.

State solves both problems.

What state is

State is data that a component remembers between renders, and when it changes, React renders the component again with the new value. You create it with the useState hook:

App.jsx
JSX
function App() {
  const [count, setCount] = React.useState(0);

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

useState(0) gives you two things in a pair:

  • count: the current value (starts at 0).
  • setCount: a function to change it. Calling it tells React “this value changed, please render again”.

The next lesson, The useState Hook, explains the syntax. Here is the flow you should remember:

  1. The component renders and shows the current state.
  2. The user does something (click, type).
  3. Your event handler calls the setter with a new value.
  4. React renders the component again, and useState now returns the new value.
  5. React updates the screen.

State belongs to a component instance

Each copy of a component on the screen has its own state. Two counters count separately:

App.jsx
JSX
function Counter({ name }) {
  const [count, setCount] = React.useState(0);
  return <button onClick={() => setCount(count + 1)}>{name}: {count}</button>;
}

function App() {
  return (
    <div style={{ display: "flex", gap: 8 }}>
      <Counter name="Counter A" />
      <Counter name="Counter B" />
    </div>
  );
}

Click A and B stays put. The state lives in React, attached to the position of each component in the tree.

When something should be state

State is for data that changes over time and that the screen must reflect: the text in an input, whether a menu is open, the items in a cart, which tab is selected. If a value never changes, use a constant. If you can calculate it from other state, calculate it (see Derived State).

State vs a ref vs a variable

UseWhen
Local variableTemporary values inside one render
State (useState)Data the screen must show; changing it should re-render
Ref (useRef)A value to remember between renders that should not re-render, such as a timer id; see useRef

Key points

  • Normal variables neither persist between renders nor trigger a re-render.
  • State is a component’s memory; changing it re-renders the component.
  • Each instance of a component has its own state.