Simplifying HTTP Requests in React with Custom Hooks

Simplifying HTTP Requests in React with Custom Hooks

1 3 7
calendar_todayschedule3 min read
— Originally published at dev.to

When building React applications, dealing with HTTP requests is inevitable. A common challenge developers face is managing the complexity of making API calls, handling loading states, errors, and displaying fetched data efficiently.

This article is going to cover how to simplify HTTP requests using custom hooks in React. We’ll cover:

  • Creating a reusable custom hook

  • Managing loading, error, and data states

  • Implementing the hook in a React component

By the end, you’ll have a cleaner and more reusable approach for handling data fetching in your applications!

Why Custom Hooks?

Custom hooks allow you to encapsulate logic that can be reused across different components. Instead of cluttering each component with API calls, state management, and error handling, we can centralize that logic inside a hook.

This separation leads to:

  • Cleaner components

  • Easier maintenance

  • Reusability across multiple components

Here's What We’ll Build

We’re going to create a useData custom hook that can fetch data from any API, manage loading and error states, and then display that data in a React component.

Step 1: Creating the useData Hook

Let’s start by creating the hook. We’ll use the useState and useCallback hooks from React to manage data, loading, and errors.

  import { useState, useCallback } from 'react';
  export function useData<T>() {
  const [data, setData] = useState<T | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);
  
  const fetchData = useCallback(async (url: string) => {
  setIsLoading(true);
  setError(null);
  try {
     const response = await fetch(url);      
     if (!response.ok) throw new Error('Network response was not ok');
     const result: T = await response.json();
     setData(result);
     } catch (error) {
     setError(
     error instanceof Error ? error.message : 'An unknown error occurred'
     );

     } finally {
       setIsLoading(false);
     }
     }, []);
     

     return { data, isLoading, error, fetchData };
     }

How It Works:

  • State Management:
    • data: Stores the fetched data.
    • error: Stores any error messages if something goes wrong.
  • fetchData Function:
    • This function uses the fetch API to make the HTTP request.
    • It handles successful responses and errors by updating the relevant state variables.
  • Type Safety with Generics:
    • By passing as a generic, we allow the hook to work with any type of data (array, object, etc.).

Step 2: Using the Hook in a Component
Now that we have the useData hook, let’s integrate it into a React component. This component will call our hook to fetch data from a sample API and handle the loading and error states.

  import React, { useEffect } from 'react';
  import { useData } from './useData'; // Import the custom hook
  const DataFetcher: React.FC = () => {
  
  const { data, isLoading, error, fetchData } = useData<any>();

    useEffect(() => {
      fetchData('https://api.example.com/data');
      }, [fetchData]);
      if (isLoading) return <p>Loading...</p>;      
      if (error) return <p>Error: {error}</p>;
       return (
     <div>
     <h2>Data Fetched:</h2>
      <pre>{JSON.stringify(data, null, 2)}</pre>
     </div>
     );
     };

     export default DataFetcher;

Key Points:

  • Fetching Data on Component Mount:
    • We’re using the useEffect hook to call fetchData when the component mounts.
  • Loading and Error Handling:
    • While the data is being fetched, a loading message is shown. If an error occurs, an error message is displayed.
  • Rendering Data:
    • Once the data is fetched, it’s displayed in a pre tag to maintain formatting.

Step 3: Enhancing the User Experience
Let’s make the UI a bit more user-friendly. We’ll add some basic styles and enhance the user experience by disabling the submit button when the form is loading.

Here’s an example of how the final component would look:

  const DataFetcher: React.FC = () => {
      const { data, isLoading, error, fetchData } = useData<any>();

    useEffect(() => {
      fetchData('https://api.example.com/data');
      }, [fetchData]);
    
       return (
         <div className="data-fetcher-container">
     <h1>Fetch Data Example</h1>
      {isLoading && <p>Loading data...</p>}
      {error && <p style={{ color: 'red' }}>Error: {error}</p>}
      {!isLoading && data && (
     <div>
          <h2>Data:</h2>
          <pre>{JSON.stringify(data, null, 2)}</pre>
     </div>
     )}
     </div>
    );
   };

Why This Approach?

  • Separation of Concerns: The useData hook abstracts away the HTTP request logic, keeping your components clean and focused on rendering.
  • Reusability: Since the hook is generic, you can use it to fetch different types of data across your application.
  • Improved UX: The hook manages loading and error states efficiently, ensuring that users have feedback throughout the data fetching process.

Key Takeaways

  • Custom Hooks are a great way to encapsulate logic and keep your components clean.
  • Handling HTTP requests in React becomes much simpler when using hooks like useData.
  • The fetch API provides a powerful and flexible way to handle HTTP requests in JavaScript.

By adopting this pattern, your components will stay focused on rendering logic while the custom hook handles data fetching, loading, and error handling.

Want more insights? Follow me here for tips on React, TypeScript, and modern web development practices!

1 Comment

0 votes
🔥 Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

How I Built a React Portfolio in 7 Days That Landed ₹1.2L in Freelance Work

Dharanidharan - Feb 9

React Native Quote Audit - USA

kajolshah - Mar 2

How Much Does a Custom Website Cost in 2026? Pricing Guide

Built2Win - Jul 2

Running OpenAPI Validation in GitHub Actions and Showing Findings in Pull Requests

Ganesh Kumar - Jul 3

Beyond the 98.6°F Myth: Defining Personal Baselines in Health Management

Huifer - Feb 2
chevron_left
141 Points11 Badges
Lagos, Nigeria
1Posts
0Comments
Experienced Frontend engineer with a track record of developing innovative and scalable applications... Show more

Related Jobs

View all jobs →

Commenters (This Week)

6 comments
1 comment
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!