React Fundamentals: Managing State with Hooks

Adam Sturge | Oct 10, 2023 min read

Overview

React hooks let you use state and other React features without writing a class. The useState hook is the most basic hook for managing state in functional components.

Steps

  1. Import the useState hook:
import React, { useState } from "react";
  1. Define state variables with the useState hook:
function Counter() {
  // Declare a state variable named "count" with initial value 0
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}
  1. Using multiple state variables:
function UserForm() {
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");

  return (
    <form>
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Name"
      />
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email"
      />
      <p>
        Current input: {name}, {email}
      </p>
    </form>
  );
}
  1. Using objects as state:
function UserForm() {
  const [user, setUser] = useState({ name: "", email: "" });

  const handleChange = (e) => {
    setUser({
      ...user, // Keep existing state
      [e.target.name]: e.target.value, // Update only what changed
    });
  };

  return (
    <form>
      <input
        name="name"
        type="text"
        value={user.name}
        onChange={handleChange}
        placeholder="Name"
      />
      <input
        name="email"
        type="email"
        value={user.email}
        onChange={handleChange}
        placeholder="Email"
      />
      <p>
        Current input: {user.name}, {user.email}
      </p>
    </form>
  );
}

Common Issues

  • Forgetting the spread operator: When updating object state, you need to include ...prevState to avoid losing other properties
  • Direct state mutation: Never modify state directly; always use the setter function
  • Asynchronous state updates: State updates may be batched for performance, so don’t rely on the state value right after setting it
  • Infinite render loops: Don’t call setState in the main component body; use events or useEffect

Additional Notes

  • The useState hook returns an array with two elements:
    1. The current state value
    2. A function to update that value
  • You can use array destructuring to give these elements any names you want
  • For complex state logic, consider using useReducer instead
  • State is preserved between renders unless the component is unmounted
  • For side effects (like data fetching), use the useEffect hook instead