Building a Reusable useFetch Hook in React with TypeScript
The useFetch hook is a common pattern in React applications for simplifying data fetching. This challenge asks you to implement a custom useFetch hook that handles fetching data from an API endpoint, managing loading states, and handling errors gracefully. A well-implemented useFetch hook promotes code reusability and improves the overall structure of your React components.
Problem Description
You need to create a custom React hook called useFetch that takes a URL as an argument and returns an object containing the following properties:
data: The fetched data from the API. Initiallyundefined.isLoading: A boolean indicating whether the data is currently being fetched. Initiallytrue.error: An error object if an error occurred during the fetch. Initiallyundefined.refetch: A function that can be called to manually trigger a re-fetch of the data.
The hook should:
- Fetch Data: Upon initial render, the hook should initiate a GET request to the provided URL.
- Manage Loading State: Set
isLoadingtotruebefore the fetch begins andfalseafter the fetch completes (regardless of success or failure). - Handle Success: If the fetch is successful, update the
dataproperty with the parsed JSON response. - Handle Errors: If the fetch fails, update the
errorproperty with the error object. - Refetch Functionality: The
refetchfunction should allow the component using the hook to manually trigger a new fetch request to the same URL. - Dependency Array: The hook should only re-fetch data when the URL changes.
Examples
Example 1:
Input: URL = "https://jsonplaceholder.typicode.com/todos/1"
Output:
{
data: { userId: 1, id: 1, title: 'delectus aut autem', completed: false },
isLoading: false,
error: undefined,
refetch: () => {} // A function to trigger a re-fetch
}
Explanation: The hook successfully fetches data from the provided URL and populates the `data` property. `isLoading` becomes false, and `error` remains undefined.
Example 2:
Input: URL = "https://jsonplaceholder.typicode.com/nonexistent-endpoint"
Output:
{
data: undefined,
isLoading: false,
error: Error: Request failed with status code 404,
refetch: () => {}
}
Explanation: The hook attempts to fetch data from a non-existent endpoint. The fetch fails, `isLoading` becomes false, and the `error` property is populated with an error object.
Example 3:
Input: Initial URL = "https://jsonplaceholder.typicode.com/todos/1", Subsequent refetch() call
Output: (After refetch())
{
data: { userId: 1, id: 1, title: 'delectus aut autem', completed: false },
isLoading: false,
error: undefined,
refetch: () => {}
}
Explanation: The `refetch` function is called, triggering a new fetch request. The hook fetches the data again and updates the `data` property.
Constraints
- The URL must be a valid string.
- The hook should use the
fetchAPI for making the HTTP request. - The hook should handle network errors gracefully.
- The hook should parse the response body as JSON.
- The
refetchfunction should not trigger a fetch immediately upon being called; it should only initiate the fetch when actually invoked. - The hook should be written in TypeScript.
Notes
- Consider using
async/awaitfor cleaner asynchronous code. - Think about how to handle potential errors during JSON parsing.
- The
refetchfunction should maintain the same URL as the initial fetch. - The initial
isLoadingstate should betrueto indicate that the data is being fetched. - Focus on creating a reusable and well-structured hook. Avoid hardcoding any specific API endpoints within the hook itself.