React Hooks

Master state management and side effects with React Hooks

Understanding React Hooks

React Hooks are functions that let you "hook into" React state and lifecycle features from function components. They were introduced in React 16.8 to allow you to use state and other React features without writing a class.

Hooks provide a more direct API to the React concepts you already know: props, state, context, refs, and lifecycle.

useState Hook

The useState Hook is the most basic Hook that lets you add state to functional components. It returns a stateful value and a function to update it.

Key Points:

  • Declares a state variable
  • Returns current state and setter function
  • Preserves state between re-renders
  • Can be used multiple times in a component

Example:

import { useState } from 'react';

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

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

useEffect Hook

The useEffect Hook lets you perform side effects in function components. It serves the same purpose as componentDidMount, componentDidUpdate, and componentWillUnmount in React classes.

Common Use Cases:

  • Data fetching
  • Subscriptions
  • DOM manipulations
  • Setting up event listeners

Example:

import { useState, useEffect } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function fetchUser() {
      try {
        const response = await fetch(`/api/users/${userId}`);
        const data = await response.json();
        setUser(data);
      } catch (error) {
        console.error('Error fetching user:', error);
      } finally {
        setLoading(false);
      }
    }

    fetchUser();
  }, [userId]); // Only re-run if userId changes

  if (loading) return <div>Loading...</div>;
  if (!user) return <div>User not found</div>;

  return (
    <div>
      <h2>{user.name}</h2>
      <p>{user.email}</p>
    </div>
  );
}

useContext Hook

The useContext Hook lets you subscribe to React context without introducing nesting. It accepts a context object and returns the current context value.

When to Use:

  • Sharing global state
  • Theming
  • User preferences
  • Authentication state

Example:

import { createContext, useContext } from 'react';

const ThemeContext = createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext);
  
  return (
    <button className={`btn-${theme}`}>
      Themed Button
    </button>
  );
}

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <ThemedButton />
    </ThemeContext.Provider>
  );
}

useRef Hook

The useRef Hook returns a mutable ref object whose .current property is initialized to the passed argument. It's useful for accessing DOM elements and storing mutable values that don't trigger re-renders.

Common Use Cases:

  • Accessing DOM elements
  • Storing previous values
  • Managing focus, text selection, or media playback
  • Triggering imperative animations

Example:

import { useRef, useEffect } from 'react';

function TextInputWithFocusButton() {
  const inputRef = useRef(null);

  const focusInput = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>
        Focus the input
      </button>
    </div>
  );
}

Hooks Best Practices

1. Only Call Hooks at the Top Level

Don't call Hooks inside loops, conditions, or nested functions. Always use Hooks at the top level of your React function.

2. Only Call Hooks from React Functions

Don't call Hooks from regular JavaScript functions. Only call Hooks from React function components or custom Hooks.

3. Use Multiple useEffect Hooks

Split different concerns into multiple useEffect calls instead of putting all logic in a single useEffect.

4. Clean Up Effects

Always clean up subscriptions, event listeners, and other side effects in the useEffect cleanup function.

Next Steps

Now that you understand React Hooks, you might want to explore: