AK

Ankur Kedia

Ankur

BlogProjects

DIY: Writing custom React Hooks to perform async operations

How to creating your own useFetch hook to make API calls.

6 Oct, 20203 min read
Custom Hooks

This article is about creating your own React Hooks to perform async operations. As an example, we will create a custom useFetch Hook to make API calls.

What are Hooks?

Hooks are functions which let you use state and other React features without writing a class. They are a new addition in React 16.8. You can check the overview of Hooks before moving ahead. One important thing about Hooks is that they can only be used either in a functional component or inside another Hook.

Why custom Hooks?

A custom Hook allows you to extract some components logic into a reusable function. It is a reusable JavaScript function that can call other Hooks.

Rules of Hooks

Hooks are JavaScript functions, but they impose two additional rules:

  • Only call Hooks at the top level. Don't call Hooks inside loops, conditions, or nested functions.
  • Only call Hooks from React function components. Don't call Hooks from regular JavaScript functions.

What are we trying to achieve here?

There are no bounds to the functionality that you can achieve using Hooks. But, in this article, we are just creating a specific type of custom Hook to perform async operations (API calls in this example) and tailor it to fit our use-cases. We will also have a function fetchNow that can be used to fetch the data with a callback. This should be the basic API for our example Hook.

const { data, loading, error } = useFetch(
"https://www.reddit.com/r/popular.json"
);

Alternative API could be the following.

const { data, loading, error, fetchNow } = useFetch();

We will start with creating our Hook and we will name it useFetch. It takes url and options as parameters. We will use useState and useEffect Hooks internally to implement our Hook.

useFetch.ts
function useFetch(url: string, options?: any) {
const [data, setData] = useState();
const [loading, setLoading] = useState(false);
const [error, setError] = useState();
function fetchNow(url: string, options?: any) {
// we will add the code here
}
useEffect(() => {
fetchNow(url, options);
}, []);
return { data, loading, error, fetchNow };
}

To prevent the extra re-renders. We will merge our setState Hooks.

useFetch.ts
function useFetch(url: string, options?: any) {
const [status, setStatus] = useState<{
loading: boolean;
error?: Error;
data?: any;
}>({
loading: false
});
function fetchNow(url: string, options?: any) {
// we will add the code here
}
useEffect(() => {
fetchNow(url, options);
}, []);
return { ...status, fetchNow };
}

Now, we have the bare-bones of our Hook ready. You can add the code according to the functionality of the Hook you are creating. In our case, we need to add the API calls. We will use the fetch API for this. After adding the logic, our function looks like this.

useFetch.ts
function useFetch(url?: string, options?: any) {
const [status, setStatus] = useState<{
loading: boolean;
error?: Error;
data?: any;
}>({
loading: false
});
function fetchNow(url: string, options?: any) {
setStatus({ loading: true });
fetch(url, options)
.then((res: any) => res.json())
.then((res: any) => {
setStatus({ loading: false, data: res.data });
})
.catch((error: Error) => {
setStatus({ loading: false, error });
});
}
useEffect(() => {
if (url) {
fetchNow(url, options);
}
}, []);
return { ...status, fetchNow };
}

The function is complete now. We will use them in our functional component like the initially expected API or with a callback like in the code shown below. And we will get the fetched data status in the variables named data, loading, error.

<button onClick={() => fetchNow("https://www.reddit.com/r/popular.json")}>
Fetch data
</button>

TL;DR

You can check the sandbox below for the complete functionality of Hook.

Edit useFetch

What's next?

  • Cancelling Request: We can add the option to cancel the requests.
  • Caching: We can add a caching layer so that it does not have to make API calls for the same requests multiple times.
  • Central Error Handling: We can add an option to dispatch the error to a central handler in the project.

Conclusion

This is just one of the common use-cases of custom hooks. You can achieve a lot of great things with them. You got the idea on how to create custom Hooks. Here, we just made the API calls inside the Hook, but you can do all sorts of async operations using the same idea.

Thanks for reading. Hope you found it helpful! Happy coding!

Discuss on Twitter

Share on