Effortless HTTP requests in React with the Facade pattern

Hey there! Today, I want to talk about the Facade pattern and the convenience of using a custom useHttp React hook.

In software development, the Facade pattern is a structural design pattern that provides a simplified interface to a complex system. The idea is to create a high-level interface that makes it easier to interact with the underlying system.

This pattern can be incredibly useful when dealing with HTTP requests. Making API calls can be a complex process that involves a lot of code. However, with a Facade, we can create a simplified interface that handles all the complexities of making an API call, allowing us to focus on the more important parts of our application.

That's where the useHttp React hook comes in. It provides a simple interface for making HTTP requests in a React component. With this hook, you don't have to worry about setting up fetch requests, handling loading states, or error handling. It abstracts all of these details and allows you to focus on what really matters - the data.

Let's take a closer look at the code for this hook:

import { useState } from "react";

type HttpMethods = "GET" | "POST" | "PUT" | "DELETE";

const useHttp = () => {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<unknown | null>(null);
  const [data, setData] = useState(null);

  const sendRequest = async (
    url: string,
    method: HttpMethods,
    options: RequestInit,
    body?: unknown
  ) => {
    try {
      setLoading(true);
      const response = await fetch(url, {
        method,
        mode: "cors",
        credentials: "include",
        ...options,
        body: body ? JSON.stringify(body) : undefined,
      });
      const json = await response.json();
      setLoading(false);

      // No error, operation successful
      setData(json);
      return json;
    } catch (err) {
      // for all unexpected errors not handled on backend error handling
      setError(err);
      setLoading(false);
      setData(null);
    }
  };

  const get = async (url: string, options: RequestInit = {}) => {
    return sendRequest(url, "GET", options);
  };

  const post = async (
    url: string,
    body: unknown = {},
    options: RequestInit = {}
  ) => {
    return sendRequest(url, "POST", options, body);
  };

  const put = async (
    url: string,
    body: unknown = {},
    options: RequestInit = {}
  ) => {
    return sendRequest(url, "PUT", options, body);
  };

  const remove = async (url: string, options: RequestInit = {}) => {
    return sendRequest(url, "DELETE", options);
  };

  return { loading, error, data, get, post, put, remove };
};

export default useHttp;

As you can see, the hook defines four different HTTP methods: get, post, put, and remove. These methods all make use of a sendRequest function that handles the details of making a fetch request.

The useHttp hook also manages loading and error states, allowing you to easily update your UI based on the status of the request. This can be incredibly useful when dealing with complex applications that make a lot of API calls.

Overall, the useHttp hook provides a simplified interface for making HTTP requests in a React component. It's a great example of how the Facade pattern can be used to simplify complex systems and make them more manageable.

Updated:


Comments