skip to Main Content

I want to reduce my general dependency on useEffects and have created a hook file that fetches from an api

I have the following code setup:

    const searchCharactersAPI = useCallback(async () => {
        try {
            setLoading(true);
            const res = await fetch(
                `https://narutodb.xyz/api/character${
                    search !== "" ? `/search?name=${search}` : ""
                }`,
            );
            const resJSON = await res?.json();

            setCharactersData(resJSON);
        } catch (error) {
            console.log("There was an error", error);
        } finally {
            setLoading(false);
        }
    }, [search]);

  const handleSearch = (e: ChangeEvent<HTMLInputElement>) => {
    setSearch(e.target.value)
  }


 <input className="flex w-full border-0 outline-none focus-visible:false rounded-lg p-2 text-black" placeholder="Search characters..." type="text" onChange={handleSearch} value={search} />

if i was to change the searchCharactersAPI useCallback fn to a useEffect it will work as expected but i am wondering why it doesnt fire when it is a useCallback when exact same dependencies

2

Answers


  1. useCallback doesn’t call the function every time a dependency changes. It just returns a new function reference. Either you have to call the function in the useCallback, or you have to call the searchCharactersAPI in handleSearch.

    On a side note, if you’re trying to remove effects from your code, then using useCallback to execute side effects is not the way to go. Handle user events in an event handler like you are supposed to.

    Login or Signup to reply.
  2. The useCallback hook memoizes the function instance and only changes it when its dependencies change. If the search state is not changing, the searchCharactersAPI function won’t be updated, and therefore, the effect won’t be triggered.

    You can try using the useEffect hook directly and include search as a dependency in the dependency array.

    useEffect(() => {
        const searchCharactersAPI = async () => {
            try {
                setLoading(true);
                const res = await fetch(
                    `https://narutodb.xyz/api/character${
                        search !== "" ? `/search?name=${search}` : ""
                    }`,
                );
                const resJSON = await res?.json();
    
                setCharactersData(resJSON);
            } catch (error) {
                console.log("There was an error", error);
            } finally {
                setLoading(false);
            }
        };
    
        searchCharactersAPI();
    }, [search]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search