Should this simple fetch be in a function or a custom hook?

Viewed 31

To start, I am using NextJs.

Out of curiosity, would it be ok to put this fetch in a regular function or would you have to put this in a custom hook and why?

Also what is best practice and what is your personal style? Do you put your fetches in hooks or functions? What about if you have to conditionally render a fetch? Do you put them in functions and then just wrap them in a hook?

Example below of a simple hook.

export default async function useFetchTopRatedCatagory() {
  const res = await fetch(
    `https://api.themoviedb.org/3/movie/top_rated?api_key=f70b3ca617a5d8978429e375c55a4fa2&language=en-US&page=1`
  );
  const data = await res.json();
  //   console.log("THIS IS MY TEST HELOOOOOOOOOOOO3480280483204803280432", data);

  return data;
}
1 Answers

In a common environment, you can't just call an API in a component's render function (independent of functional or class components), because this will result in a API call everytime the component rerenders.

That's why such calls are often inside a useEffect call combined with a useState:

const FooComponent = () => {
    const [data, setData] = useState();

    useEffect(() => {

        const runFetch = async () => {
            const res = await fetch(
                `https://api.themoviedb.org/3/movie/top_rated?api_key=f70b3ca617a5d8978429e375c55a4fa2&language=en-US&page=1`
            );
            const data = await res.json();

            setData(data);
        }

        runFetch();
    }, []); // no dependencies!!!

    return <div>{JSON.stringify(data)}</div>
}

If you're components get large or you use the endpoint on a second place, you might want to use a custom hook. But the same logic applies: You can't just use fetch inside the function, because it get's called everytime a component that uses your hook gets rerendered. You can refactor the above component to use a custom hook:

const useTopRatedCategory = () => {
    const [data, setData] = useState();

    useEffect(() => {

        const runFetch = async () => {
            const res = await fetch(
                `https://api.themoviedb.org/3/movie/top_rated?api_key=f70b3ca617a5d8978429e375c55a4fa2&language=en-US&page=1`
            );
            const data = await res.json();

            setData(data);
        }

        runFetch();
    }, []); // no dependencies!!!
    
    // data will only be set once nad therefore be always the same
    return data;
}

const FooComponent = () => {
    const data = useTopRatedCategory();

    return <div>{JSON.stringify(data)}</div>
}

Conditionals

Conditionals basically work the same. You should know, that you can't use hooks behind conditional statements (React Docs). But if you think about it, conditional variables are just changing dependencies. And are able to change state inside an if. That said, you might call page in the following example conditional:

import {
    useState
} from "../../../../.local/share/JetBrains/Toolbox/apps/PhpStorm/ch-0/222.4167.33/plugins/JavaScriptLanguage/jsLanguageServicesImpl/external/react";

const useTopRatedCategory = (page = 1) => {
    const [data, setData] = useState();

    useEffect(() => {

        const runFetch = async () => {
            const res = await fetch(
                `https://api.themoviedb.org/3/movie/top_rated?api_key=f70b3ca617a5d8978429e375c55a4fa2&language=en-US&page=${page}`
            );
            const data = await res.json();

            setData(data);
        }

        runFetch();
    }, [page]); // page as dependency

    // data will only be set once nad therefore be always the same
    return data;
}

const FooComponent = () => {
    const [page, setPage] = useState(1)

    
    const data = useTopRatedCategory(page);

    return <div>
        {JSON.stringify(data)}
        
        <button onClick={() => setPage(page + 1)}>Increment Page</button>
    </div>
}

Inside the button's onClick callback handler, you can set the page to whatever you want. You can use if or any other construct that you are disallowed otherwise.

A nice, more in depth tutorial can be found here: https://www.benmvp.com/blog/conditional-react-hooks/

Related