DEV Community

Anxiny
Anxiny

Posted on

A Custom React Hook that handles duplicate API call

Today, we are going to create a custom hook that solve this problem:

  • We have multiple components that calling same API.
  • Component may not always be on same page, therefore, they have to call the API by themselves.

Here is a example hook I think can handle this problem:

let isCalling = new Map(); // This can be replace by some global state. I use this for the sake of simplicity.
function useFetch(url) {
  const [data, setData] = useState("");
  useEffect(() => {
    let isThisAPICalling = isCalling.get(url);
    if (!isThisAPICalling) {
      console.log("new");
      isThisAPICalling = fetch(url).then((response) => response.json());
      isCalling.set(url, isThisAPICalling);
      // The body can only be parsed once.
    }
    isThisAPICalling.then((json) => {
      console.log("done");
      console.log(json.title);
      isCalling.delete(url);
      setData(json.title);
    });
  }, []);
  return data;
}
Enter fullscreen mode Exit fullscreen mode

Here is a demo.

Thank you all! Please let me know if you have any suggestion.

Oldest comments (2)

Collapse
 
alfredosalzillo profile image
Alfredo Salzillo

Maybe you wanted to implement an useDebounce

GitHub logo xnimorz / use-debounce

A debounce hook for react

Features

Install

yarn add use-debounce
# or
npm i use-debounce --save
Enter fullscreen mode Exit fullscreen mode

Demos

The simplest way to start playing around with use-debounce is with this CodeSandbox snippet codesandbox.io/s/kx75xzyrq7

More complex example with searching for matching countries using debounced input: codesandbox.io/s/rr40wnropq (thanks to twitter.com/ZephDavies)

Changelog

github.com/xnimorz/use-debounce/bl...

Simple values debouncing

According to twitter.com/dan_abramov/status/106...

import React, { useState } from 'react';
import { useDebounce } from 'use-debounce';
export default function Input() {
  const [text, setText] = useState('Hello');
  const [value] = useDebounce(text, 1000);
  return (
    <div>
      <input
        defaultValue={'Hello'}
        onChange={(e) => {
          setText(e.target.value);
        }}
      />
      <p>Actual value: {text}</
Enter fullscreen mode Exit fullscreen mode
Collapse
 
anxiny profile image
Anxiny

Thanks for replying.

But I feel like this is for the function that is repeatly called in one component.
Here is multiple components calling same api.