React

Getting Started with React Hooks

Learn the fundamentals of React Hooks, including useState, useEffect, and custom hooks, to simplify your component logic.

May 15, 2025
5 min read
By useLines Team
ReactHooksJavaScriptFrontenduseStateuseEffect
Illustration for Getting Started with React Hooks

Understanding React Hooks

React Hooks allow you to use state and other React features in function components, without writing a class. Introduced in React 16.8, they revolutionize how you write components by making them cleaner, easier to test, and simpler to reason about.

Before Hooks, you had to convert a function component to a class component if you needed to add state or use lifecycle methods. Hooks let you do all of that and more within functional components.

The Rules of Hooks

To ensure Hooks work correctly, you must follow two simple rules:

  1. Only Call Hooks at the Top Level: Don't call Hooks inside loops, conditions, or nested functions. This ensures that Hooks are called in the same order each time a component renders, which allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls.
  2. Only Call Hooks from React Functions: Call Hooks from React function components or from custom Hooks. Don't call them from regular JavaScript functions.

The useState Hook

The useState hook is the most common hook and is used to add state to a functional component.

Here's how it works:

import React, { useState } from 'react';

function Counter() {
  // useState returns a pair: the current state value and a function that lets you update it.
  const [count, setCount] = useState(0);

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

In this example, useState(0) initializes our state count with 0. setCount is the function we use to update the count state. When setCount is called, React re-renders the Counter component with the new count value.

The useEffect Hook

The useEffect hook lets you perform side effects in function components. It is a close replacement for componentDidMount, componentDidUpdate, and componentWillUnmount in class components.

Side effects can include data fetching, subscriptions, or manually changing the DOM.

Here is an example of fetching data with useEffect:

import React, { useState, useEffect } from 'react';

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

  useEffect(() => {
    async function fetchUser() {
      const response = await fetch(`https://api.example.com/users/${userId}`);
      const data = await response.json();
      setUser(data);
    }

    fetchUser();
  }, [userId]); // The dependency array

  if (!user) {
    return <p>Loading...</p>;
  }

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

The second argument to useEffect is the dependency array. The effect will only re-run if the values in this array change. If you pass an empty array [], the effect will only run once after the initial render.

Custom Hooks

Custom Hooks allow you to extract component logic into reusable functions. A custom hook is a JavaScript function whose name starts with "use" and that may call other Hooks.

Let's create a custom hook to track the window width:

import { useState, useEffect } from 'react';

function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    const handleResize = () => setWidth(window.innerWidth);
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return width;
}

Now you can use this custom hook in any component to get the current window width:

function MyComponent() {
  const width = useWindowWidth();

  return <p>Window width is {width}px</p>;
}

Custom Hooks are a powerful way to share stateful logic, reduce duplication, and keep your components clean and focused on their specific tasks. By adopting hooks, you can write more declarative and maintainable React applications.

Related Posts