TanStackT
TanStack3y ago
6 replies
sad-indigo

"Clean" way to centralize API calls in RQ while still keeping some typesafety?

Currently I have something like this (using ky which is kinda like axios)
export const api = {
    useGetPlaylists: () => {
        return useQuery(['playlists'], async () => {
            const res = await ky.get('playlists');
            const playlistsResponse: Response_Query_GetPlaylists = await res.json();
            return playlistsResponse;
        });
    },
    useGetPlaylist: (playlistId: string | number) => {
        return useQuery(['playlists', playlistId], async () => {
            const res = await ky.get(`playlists/${playlistId}`);
            const playlistResponse: Response_Query_GetPlaylist = await res.json();
            return playlistResponse;
        });
    },
};

And usage would be:
export const PlaylistsPage = () => {
    const query_GetPlaylists = api.useGetPlaylists();
        // `query_GetPlaylists.data` is properly typed as `Response_Query_GetPlaylists` which is, for simplicity, a `Playlist[]`

    return /*... some TSX */

But this looks kind of ugly to me, though I have no idea how it's usually implemented. This is basically just writing 1 custom hook for every single kind of API call I would have, which doesn't seem right.

I tried one other version with a single custom hook called useApi() which accepted all kinds of props, and returns a specific useQuery() call for that query only (though this looks like it violates the rules of hooks), however the problem with this is that const { data } = useApi() would type data as a union of all possible return types instead, ruining any typesafety I'd have.
Was this page helpful?