State is used by React components to store information about the components. It’s quite similar to props, but state is private to the component in which it’s defined. As a beginner in React, you can simply think of state as the data that the given component is managing.

Counter app

useState hook is one of the simplest of all built-in hooks. However, I think that it’s one of the most important ones. It’s used widely to manage the data in our applications. State is best explained with the classic ‘counter’ example. Let’s take a look.

import { useState } from 'react'

function App() {
  const [count, setCount] = useState(0)
  
  return (
    <div></div>
  );
}

export default App;

In the above code App.js example we have called the useState(), passed it the initial state argument of the integer 0 and grabbed the return pair of values.

Calling useState hook declares the state variable. State variable differs from a normal variable defined within the body of the component in that it is preserved between further re-renders of the component (more on that later).

Try to use regular variables and see if they behave the way you’d expect them to do… They don’t!

We passed the initial value of 0 to as an argument when calling useState. This instantiates the state variable with a value equal to 0. In this example, we used the numerical value, but state is not limited to those. You can use either a string, an array or any other type that makes sense to your application.

useState returns a pair of values. The first one is the current state of the function and the second is a function that’s used to update this value. We use the const [value, function] = useState() syntax to save those.

We can use the value of our state just like any other variable. For instance, we can render it for the user to see.

import { useState } from 'react'

function App() {
  const [count, setCount] = useState(0)
  return (
    <div>
      <h2>Current count: {count}</h2>
    </div>
  );
}

export default App;

We cannot however modify this value directly. If we want to change the value of the count variable we need to use the setCount function.

import { useState } from "react";

function App() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <h2>{count}</h2>
      <button onClick={setCount(count + 1)}>Increase by 1</button>
      <button onClick={setCount(count - 1)}>Decrease by 1</button>
    </div>
  );
}
export default App;

We have added two buttons to our applications, one for incrementing the current value of state by one and the other for decrementing it by one.

On click of the button we’re calling the arrow function with the setCount(count + 1) and setCount(count – 1). Notice how we’re not modifying the existing state variable but passing a new one.

The expression count + 1 is in reality evaluated to a number. So it’s equivalent to calling setCount(1) (since count is equal to 0 on the first render). This is actually quite important for you to grasp to be able to use state effectively!

Blog comment

Let’s take a look at a slightly more complicated app. We’re going to see how to use state to gather some data from the users and display it on the screen. For that reason, we can simulate commenting on a blog.

function App() {
  return (
    <div>
      <form>
        <label>
          Name:
          <input type="text" />
        </label>
        <label>
          Surname:
          <input type="text" />
        </label>
        <label>
          Age:
          <input type="number" />
        </label>
        <button type="submit">Submit</button>
      </form>
    </div>
  );
}
export default App;

In the above example, we have created a form that expects the user to input 3 fields. Given that this article is focused on explaining how to use state variables, we will skip validating the input fields and assume that correct values are always provided.

The next step is to define state variables, one for each input field.

import { useState } from "react";

function App() {
  const [name, setName] = useState("");
  const [surname, setSurname] = useState("");
  const [age, setAge] = useState("");
	
  return (
    <div style={{ marginLeft: "50px" }}>
      <form>
        <label>
          Name:
          <input
            type="text"
            value={name}
            onChange={(event) => setName(event.target.value)}
          />
        </label>
        <label>
          Surname:
          <input
            type="text"
            value={surname}
            onChange={(event) => setSurname(event.target.value)}
          />
        </label>
        <label>
          Age:
          <input
            type="number"
            value={age}
            onChange={(event) => setAge(event.target.value)}
          />
        </label>
        <button type="submit">Submit</button>
      </form>
    </div>
  );
}
export default App;

At this point we can use the input fields, however, we are not storing the data in any way. Let’s create a new state variable called users. We’re also going to create a submission handler that’s going to execute when the page user submits the form.

import { useState } from "react";

function App() {
  const [name, setName] = useState("");
  const [surname, setSurname] = useState("");
  const [age, setAge] = useState("");
  const [users, setUsers] = useState([]);

  const handleSubmit = (event) => {
    event.preventDefault();
    setUsers([...users, { name, surname, age }]);
    setName("");
    setSurname("");
    setAge("");
  };

  return (
    <div style={{ marginLeft: "50px" }}>
      <form onSubmit={handleSubmit}>
        <label>
          Name:
          <input
            type="text"
            value={name}
            onChange={(event) => setName(event.target.value)}
          />
        </label>
        <label>
          Surname:
          <input
            type="text"
            value={surname}
            onChange={(event) => setSurname(event.target.value)}
          />
        </label>
        <label>
          Age:
          <input
            type="number"
            value={age}
            onChange={(event) => setAge(event.target.value)}
          />
        </label>
        <button type="submit">Submit</button>
      </form>
      <ul>
        {users.map(({ name, surname, age }) => (
          <li>
            Name: {name}, Surname: {surname}, Age: {age}
          </li>
        ))}
      </ul>
    </div>
  );
}
export default App;

Now we should have a fully functional form. It’s going to get some data from the users. Append it to the users state variable and display them back to the page users.

Avatar photo
👋 Hey, I'm Dawid Budaszewski
Hello! I'm Dawid. I'm a full-stack developer with a couple of years of experience under my belt. I spent most of my career working with React. Now it's time to pass the knowledge onto somebody else!

💬 Leave a comment

Your email address will not be published.

We will never share your email with anyone else.