Custom Hooks - anastasiamexa/react-complete-guide-course-resources GitHub Wiki

Custom hooks are a powerful and flexible feature in React that allows you to extract and reuse stateful logic across different components. They are functions that can contain hooks (such as useState, useEffect, etc.) and can be shared and reused across different parts of your application. Custom hooks follow the naming convention of starting with the word "use" to distinguish them as hooks.

In this case, let's assume a custom hook called useFetch. Let's break down the code:

import { useEffect, useState } from 'react';

export function useFetch(fetchFn, initialValue) {
  const [isFetching, setIsFetching] = useState();
  const [error, setError] = useState();
  const [fetchedData, setFetchedData] = useState(initialValue);

  useEffect(() => {
    async function fetchData() {
      setIsFetching(true);
      try {
        const data = await fetchFn();
        setFetchedData(data);
      } catch (error) {
        setError({ message: error.message || 'Failed to fetch data.' });
      }

      setIsFetching(false);
    }

    fetchData();
  }, [fetchFn]);

  return {
    isFetching,
    fetchedData,
    setFetchedData,
    error
  };
}

Here's a breakdown of the key elements in useFetch custom hook:

1. Importing React Hooks:

  • The hook imports useEffect and useState from React. These are standard React hooks that enable you to manage side effects and state in functional components.

2. Function Signature:
The useFetch function takes two parameters: fetchFn and initialValue.

  • fetchFn is a function that is expected to return a promise. This function represents the logic for fetching data.
  • initialValue is the initial value for the fetchedData state.

3. State Variables:
Three state variables are declared using the useState hook:

  • isFetching: A boolean flag indicating whether the data is currently being fetched.
  • error: An object representing any error that occurred during the fetch. It includes a default message if no specific error message is provided.
  • fetchedData: The actual data fetched from the API.

4. useEffect Hook:

  • The useEffect hook is used to initiate the fetching of data when the component mounts. It depends on the fetchFn parameter.
  • Inside the useEffect, the fetchData function is defined. It sets isFetching to true, then tries to fetch the data using the provided fetchFn. If successful, it updates the fetchedData state; otherwise, it sets an error.
  • Regardless of success or failure, it sets isFetching back to false to indicate the end of the fetch operation.

5. Return Statement:

  • The custom hook returns an object with the state variables isFetching, fetchedData, setFetchedData and error. Components using this hook can destructure these values directly.

Example Usage:

import React from 'react';
import { useFetch } from './useFetch';

const MyComponent = () => {
  const { isFetching, fetchedData, setFetchedData, error } = useFetch(fetchData, []);

  // Assume fetchData is a function that returns a promise (e.g., fetch)
  async function fetchData() {
    const response = await fetch('https://api.example.com/data');
    if (!response.ok) {
      throw new Error('Failed to fetch data');
    }
    return response.json();
  }

  // Update fetchedData manually based on some user interaction
  const handleUpdateData = async () => {
    try {
      const newData = await someCustomFetchFunction();
      setFetchedData(newData);
    } catch (error) {
      console.error('Error updating data:', error);
    }
  };

  return (
    <div>
      <h1>Data Display</h1>

      {isFetching && <p>Loading...</p>}
      {error && <p>Error: {error.message}</p>}

      {fetchedData.length > 0 && (
        <ul>
          {fetchedData.map(item => (
            <li key={item.id}>{item.name}</li>
          ))}
        </ul>
      )}

      <button onClick={handleUpdateData}>Update Data</button>
    </div>
  );
};

export default MyComponent;

By using the useFetch hook, you encapsulate the fetching logic, making it reusable across different components. This abstraction promotes cleaner, more modular, and more maintainable code.

⚠️ **GitHub.com Fallback** ⚠️