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
anduseState
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 thefetchedData
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 thefetchFn
parameter. - Inside the
useEffect
, thefetchData
function is defined. It setsisFetching
totrue
, then tries to fetch the data using the providedfetchFn
. If successful, it updates thefetchedData
state; otherwise, it sets an error. - Regardless of success or failure, it sets
isFetching
back tofalse
to indicate the end of the fetch operation.
5. Return Statement:
- The custom hook returns an object with the state variables
isFetching
,fetchedData
,setFetchedData
anderror
. 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.