Hubert
8 min
October 9, 2024

Introduction to hooks and their role in React.js

React hooks are features introduced in React 16.8 that allow state and other React solutions to be used in function components. Hooks simplify the creation and management of logic in React applications. With hooks like useState and useEffect, developers can manage state, handle side effects (such as fetching data), and optimise performance without writing class components.

Read more
Introduction to hooks and their role in React.js

React Hooks in React JS

Hooks in React.js solve several challenges that previously prevented the creation of more complex functional components. 

First, they allow for better code organisation. This is particularly useful when component logic becomes complex. With hooks such as useState or useEffect, logic can be more easily broken down into smaller, independent functions, making it easier to read and debug.

Another benefit of hooks is the ability to eliminate duplicate code. The same code related to the component’s lifecycle could be repeated in traditional class components using different methods. Hooks such as useEffect allow other aspects of the logic, such as data retrieval and state updating, to be combined in one place.

Hooks also make it easier to reuse logic between different components. Instead of creating complex structures based on higher-order components (HOCs), you can easily extract logic into your hooks, making your code more modular and scalable.

What are the most commonly used hooks in React.js?

Learn about the most commonly used hooks, their functions, and usage:

Description and usage of useState

useState is one of the most widely used hooks in React.js. It allows you to add a state to a function component. It will enable us to store a value in the component’s internal state and update it in response to user interaction. With useState, we can define a state variable and a function to update it. This hook takes the initial value of the state as an argument and returns an array where the first element is the current value of the state and the second element is the function that allows it to be changed.

Usage: useState is excellent for simple cases like counting button clicks, turning on or off a button, or storing form data.

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

Examples of useEffect and how it manages the lifecycle of a component

useEffect is a hook that allows you to manage side effects in function components, such as data retrieval, subscriptions, or DOM manipulation. This hook is equivalent to the lifecycle methods in the component class, such as componentDidMount, componentDidUpdate, and componentWillUnmount. useEffect takes a function executed each time the component is rendered and an optional dependency array that controls when the effect should be called.

Usage: useEffect is often used to retrieve data from the API, subscribe to data streams, or respond to changes in application state. It can also be used to clean up side effects, such as canceling subscriptions or timers, as part of application optimisation.

useEffect(() => {
  // Fetch data when the component is loaded
  fetchData();
  return () => {
    // Clean up the effect after the component has finished running
    cleanup();
  };
}, [dependency]); // The effect is triggered when the dependency changes

Using useContext to manage the global state

useContext is a hook that allows you to access the global context without manually passing props between components. This allows easy application state management at different component tree levels. useContext works with the Context API, enabling you to create global data. I.e., theme settings, user data, or permissions available throughout the application without passing through other components.

Usage: useContext helps manage global state, such as storing information about the logged-in user, the application theme, or language settings.

const theme = useContext(ThemeContext);

What are custom hooks, and how do I create them?

Custom hooks in React.js are functions that allow you to extract and reuse logic that can be repeated in multiple components. Custom hooks work like built-in hooks like useState or useEffect. However, they enable fragments of logic to be collected into a single function that can easily be used in different places in the application.

The primary uses for custom hooks are

Reuse logic, such as form state management or side effects (data retrieval).

Better code organisation – separating complex logic from components.

Simplify functional components – improving readability and maintainability.

Custom hooks are created just like regular JavaScript functions. They can use other hooks, such as useState or useEffect, and then return a value or function used in the component.

Examples of simple custom hooks and how to implement them

Custom hooks allow repetitive logic to be organized and readable. This makes the code more modular and easier to maintain. They can be reused many times in different application parts, simplifying functional components and eliminating code duplication.

Custom form state management hook

This is a form management hook that stores the values of form fields in state and automatically updates them when changes are made:

import { useState } from 'react';

function useForm(initialValues) { 
  const [values, setValues] = useState(initialValues)

  const handleChange = (e) => {
    setValues({
      ...values,
      [e.target.name]: e.target.value,
    });
  };

  return [values, handleChange];
}

// Example of use in a component:
const [formValues, handleInputChange] = useForm({ name: '', email: '' });

Custom data fetch hook (fetch)
This hook manages the process of fetching data from the API, as well as handling loading state and errors:
import { useState, useEffect } from 'react

function useFetch(url) {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try { try
        const response = await fetch(url)
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
}

Custom data fetch hook (fetch)

This hook manages the process of fetching data from the API, as well as handling loading state and errors:

import { useState, useEffect } from 'react';

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
}

// Przykład użycia w komponencie:
const { data, loading, error } = useFetch('https://api.example.com/data');

What are the rules for using hooks?

The rules for using hooks are very important because they help maintain the stability of the state and life cycle of the components and ensure that hooks work correctly. 

Hooks in React.js must obey a few essential rules. Firstly, they can only be used at the top level of a component, which means they cannot be called inside loops, conditions, or nested functions. This ensures consistency in the order in which the hooks are called each time they are rendered. Secondly, hooks can only be used in function components or custom hooks. They cannot be used in class components or functions that are not React components.

How do hooks affect component performance?

Hooks can impact component performance through frequent re-rendering, especially if functions are recreated each time they are rendered. To avoid this, React provides tools such as useMemo and useCallback. useMemo stores the result of complex operations, preventing them from being repeated each time the component is refreshed. On the other hand, callback remembers functions should be used so that they do not have to be generated from scratch, reducing the number of unnecessary component renders.

How do I test components with hooks?

Testing components with hooks in React can be done using tools such as Jest and the React Testing Library. These allow you to test the hook logic and user interaction. To test the hook itself, you can use renderHook, and for components with hooks, you can test their behavior in response to different actions, such as clicks. 

For example, you can test whether useState is updated correctly after an event by simulating a button click and checking the new state.

What are the best practices for using hooks?

Maintaining a good code architecture with hooks helps ensure modularity and reusability of logic. Custom hooks help separate complex logic from components, improving readability and making the code more manageable. Creating hooks for repetitive logic, such as data retrieval or form handling, is good practice.

Remember, to maintain a good code architecture with hooks, it’s crucial to avoid pitfalls such as calling hooks in loops or conditions. Always ensure that hooks are called at the top level of the component. To prevent unnecessary rendering, use optimisations such as useMemo and useCallback to reduce the frequency of function and operation calls.

In summary, hooks in React.js are an excellent tool for effectively managing state and side effects in function components. With hooks like useState, useEffect, or useContext, developers can create more modular and readable code while avoiding duplicate logic. Custom hooks further increase the flexibility and reusability of code, resulting in better application organisation and improved performance.

Connected articles
Introduction to hooks and their role in React.js
7 min
January 9, 2025
What are HTML semantic tags and why should you use them?
HTML, or HyperText Markup Language, is the basic language that builds the structure of websites....
Learn more
Introduction to hooks and their role in React.js
8 min
December 29, 2024
Next.js - first steps and installation
Next.js is a modern React-based framework that makes it easy to create high-performance web applications....
Learn more
Introduction to hooks and their role in React.js
12 min
November 30, 2024
Introduction to Angular - basic definitions and concepts
Angular is a TypeScript-based front-end framework used to create interactive web applications. Thanks to its...
Learn more
See all
Discover more topics