Skip to main content

useFetch

Overview

The useFetch hook is a custom React hook for handling asynchronous data fetching in a functional and reusable manner. It provides a Promise-based approach to manage fetching states and allows re-fetching data with updated inputs.

Importing

To use the useFetch hook, you need to import it:

import { useFetch } from 'jmaelementsreact/hooks/useFetch'

Type Definition

type Result<a,b> = [Promise<a>, (_:b) => Promise<a>]

The useFetch hook returns a tuple:

  • The first element is a Promise<a> representing the current fetching state.
  • The second element is a function that triggers the fetch with a new input of type b.

Hook Signature

useFetch<a, b>(
fetch: (_: b) => Promise<a>,
input: b,
dependencies: React.DependencyList
): Result<a, b>

Parameters

  • fetch: A function that takes an input of type b and returns a Promise<a>. This represents the asynchronous fetch logic.
  • input: The initial input of type b used to call the fetch function.
  • dependencies: A dependency array (React.DependencyList) that determines when to re-run the effect and refetch data.

Returns

A tuple of:

  1. stateFetching: A Promise<a> representing the current fetch operation.
  2. A function to re-trigger the fetch with new input.

How It Works

  1. Initializes the fetching state (stateFetching) with a nullPromise (a placeholder promise).
  2. Runs the fetch function with the given input and updates the fetching state whenever dependencies change.
  3. Provides a memoized tuple with the current fetching state and a function to trigger the fetch manually with updated input.

Example Usage

Here’s a practical example of using useFetch:

import React from 'react'
import { useFetch } from './path/to/useFetch'

// Example fetch function
const fetchData = async (id: number): Promise<string> => {
const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
if (!response.ok) {
throw new Error('Failed to fetch data')
}
return response.json()
}

const ExampleComponent = () => {
const [postId, setPostId] = React.useState(1)

// Use the custom hook
const [dataPromise, refetch] = useFetch(fetchData, postId, [postId])

// Handle the promise result
const [data, setData] = React.useState<string | null>(null)
const [error, setError] = React.useState<Error | null>(null)

React.useEffect(() => {
dataPromise
.then((result) => setData(result))
.catch((err) => setError(err))
}, [dataPromise])

return (
<div>
<h1>Fetch Example</h1>
{error && <p style={{ color: 'red' }}>{error.message}</p>}
{data ? <p>Data: {data}</p> : <p>Loading...</p>}

<button onClick={() => refetch(postId + 1)}>Fetch Next Post</button>
<button onClick={() => setPostId(postId + 1)}>Update Post ID</button>
</div>
)
}

export default ExampleComponent

Explanation

  1. Fetching Data: The useFetch hook initializes the dataPromise with the result of fetchData.
  2. Triggering Fetch: The refetch function allows fetching new data with a different input value.
  3. Displaying Data: The dataPromise is used to update the data state when resolved or handle errors when rejected.

Best Practices

  • Dependency Management: Ensure that dependencies include all variables that should trigger a re-fetch.
  • Error Handling: Use .catch or a try-catch block to manage errors.
  • State Management: Consider managing the resolved data and errors separately for better UI feedback.

Notes

  • The nullPromise placeholder is used to initialize the stateFetching to avoid null or undefined states.
  • The hook is optimized using React.useMemo and React.useEffect to minimize unnecessary renders and recomputations.

Contributing

If you encounter issues or have suggestions for improving the useFetch hook, feel free to contribute or report an issue on the repository.