1

I have a following generic custom hook. What I want to achieve is that hook itself exposes api with api functions, which I can use in a callback. I also want a hook to be dependent on a api function parameters changes.

export const useArticleApi = <TResult>(
    callback: (committedOrderApi: ArticlesApi) => Promise<TResult>
): {
    loading: boolean;
    data: TResult | undefined;
} => {
    const callbackRef = useRef<(articlesApi: ArticlesApi) => Promise<TResult>>();
    const [data, setData] = useState<TResult | undefined>();
    const [loading, setLoading] = useState(false);

    useEffect(() => {
        callbackRef.current = callback;
    }, [callback]);

    useEffect(() => {
        (async () => {
            setLoading(true);
            const response = await apiCallWithErrorHandling(
                async () => callbackRef.current && (await callbackRef.current(articlesApi))
            );
            if (response.isSuccess) {
                setData(response?.data);
                setLoading(false);
            }
        })();
    }, [callback]);

    return { loading, data };
};

Hook usage:

const getArticlesForAllCategoriesCallback = useCallback((api: ArticlesApi) => api.getArticlesForAllCategories(
        categories.map(c => ({ id: c.id, name: c.name, pageId: c.pageId }))
), [categories]);

const { data, loading } = useArticleApi<ArticleSearchBarViewData>(api => getArticlesForAllCategoriesCallback(api));

I missing something pretty obvious, but for some reason useEffect inside the hook doesn't detect the change of callback parameter and api method is run only once. Can you spot the issue?

  • With the code you show I would expect both of the effects to be triggered each render. The parameter 'callback' you provide will be a new arrow function on each render. What you probably want to do is spilt callback and paramter, two parameters for your hook. – nil Mar 18 '22 at 16:32
  • @nil actually, I don't want to split, since the main idea is to have it generic and by wrapping ```getArticlesForAllCategories``` with ```useCallback``` I'm only expecting it to change once ```categories``` dependency changes – M.Pogorzelski Mar 18 '22 at 19:41

0 Answers0