DEV Community

Battling Bloat: How I Streamlined Data Fetches in React with a Custom useFetch Hook

Ever stare at a React component overflowing with data fetches and feeling lost in the spaghetti code?

I was there too, using a mix of fetch calls and state management libraries, leading to redundancy and complexity.

But then, I discovered the power of custom hooks! By creating a useFetch hook, I transformed my code, reducing bloat and improving maintainability.

The Problem of Bloated Data Fetches

For example, If your app is getting more complex. You might calling same fetches multiple times in different component.

Your code would be long and bloated.
You also might run into multiple useState as you providing many data to your component.
It’s also hard to debug because of intertwined data fetching and component logic.

This caused many challenges like readability, maintainability, potential bugs and errors, and difficulty of scaling the application.

Introducing The Custom React Hook

Just like creating a function outside your main component, a custom hook works just like it!

import { useEffect, useState } from "react";
import "./App.css";

function App() {
  const [token, setToken] = useState();
  const [loading, setLoading] = useState();


  useEffect(() => {
    setLoading(true)
    const fetchToken = async () => {
      const url = "https://localhost:8000";
      const response = await fetch(url, {
        method: "POST",
        headers: {
          user: 'Nyoman',
          password: "xxx",
        },
      });
      const data = await response.json();
      setToken(data.token);
      setLoading(false)
    };


    fetchToken()
  }, [])


  return (
    <>
      <h1>Fetch Token</h1>
      {loading && <h3>Loading Token...</h3>}
      {token && token}
    </>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

The code above is created in file App.jsx . It is a simple dummy component. While using the power of Custom Hooks, we can create useFetch and eliminates those unwanted long repeatable code.

Lets call it useFetch here and create that file useFetch.jsx inside of /src/hooks Folder.

import { useEffect, useState } from "react";

export const useFetch = (url, method, headers) => {
  const [fetchedData, setFetchedData] = useState();
  const [error, setError] = useState();
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    setIsLoading(true);
    const fetchData = async () => {
      try {
        const response = await fetch(url, { method, headers });
        if (!response.ok) {
          throw new Error("Network error: " + response.status);
        }
        const data = await response.json();
        setFetchedData(data);
      } catch (error) {
        setError(error);
      }
    };

    fetchData();
    setIsLoading(false);
  }, []);

  return { fetchedData, error, isLoading };
};
Enter fullscreen mode Exit fullscreen mode

This hook we just created on the codes above took url, method and headers as its parameter. Then returns the Data it just acquired, any Errors and also a Loading state.

Now, the App.jsx that was bloated can now be streamlined with just a few lines of code. Below is the code.

import "./App.css";
import { useFetch } from "./hooks/useFetch";

function App() {
  const url = "https://localhost:8000";
  const tokenHeader = {
    user: 'Nyoman',
    password: "xxx",
  };

  const { fetchedData, error, isLoading } = useFetch(url, "POST", tokenHeader);

  return (
    <>
      <h1>Fetch Token</h1>
      {isLoadingToken && <h3>Loading Token...</h3>}
      {fetchedData} // the token from API
      {error} // if any error exist
    </>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

the code above shows that with our new custom hook, the code entirely looks simple and straightforward. It gives us reduction in code complexity and overall project size.

We dont even need to call useState anymore since its already processed inside our useFetch.

Setbacks

As I was experimenting to this article, custom hooks has setbacks to continuous fetch. For example, if you need to fetch some token first then put token in header to the next fetch. It will give you undefined.
And since we cannot put custom hooks in a non-component function. it can’t be achieved by putting it in an asynchronous function.

This also gave me struggles to fetch on a button click event. hooks cant run on a non-component function, so does on callback function.

Conclusion

If you’re struggling with data fetching in your React projects, give custom hooks a try! They can significantly improve your code’s structure and maintainability.

But it also have setbacks as you can only run it on the first time when the page was loading.

Feel free to ask questions or check out my code for inspiration. Happy coding!

Top comments (0)