Avoid multiple network calls with hooks and Apollo

Viewed 206

I have a hook that makes an Graphql call

export const useGetStuff = (options?: QueryHookOptions<GetStuffResponse, GetStuffQueryArgs>) => {
    const [stuffId] = useStuffId();

    return useQuery<GetStuffResponse, GetStuffQueryArgs>(getStuff, {
        variables: { stuffId },
        notifyOnNetworkStatusChange: true,
        skip: !stuffId,
        ssr: false,
        ...options,
    });
};

And I am using this hook in one another hook

const useCustomHook = () => {
    // some unrelated stuff
    const { data: stuffData, loading } = useGetStuff();
   
    // do logic with stuffData and other unrelated stuff

    return { someProperty };
    
}

and in some component, I am using both useGetStuff and useCustomHook.

const MyComponent = () => {
    const { someProperty } = useCustomHook();
    const { data ,loading } = useGetStuff();

    // stuff
    
}

This implementation causes the getStuff query to be called twice (two network calls).

Is there a simple way to avoid that without having to keep useGetStuff only in the custom hook, since this latter should not have to be returning the stuffData.

1 Answers

You have done a pretty basic mistake where you are actually returning a new object on every hook call, so React does not know when to stop. While useGetStuff returns the whole object, so it should not be a problem, the second hook returns a new { someProperty }; object with new reference on every component call.

The way to fix that is to actually memoize the object:

const useCustomHook = () => {
    // some unrelated stuff
    const { data: stuffData, loading } = useGetStuff();
   
    // do logic with stuffData and other unrelated stuff

    return useMemo(() => {
        return { someProperty };
    }, [theThingThatShouldTriggerNewObjectCreation]);
}

You might also want to read a little bit more about such issues in this question from StackOverflow.

Related