Skip to Content

Setting up the fetcher

The next piece of the puzzle is to create a fetcher function that the application will use to request data from the server. You can find more details about it in the imports article.

The fetcher is going to implement a transformResponse function that processes all incoming data by passing it to the registry’s parse method.

In the simplest form, when we expect JSON responses only, the function looks like this:

src/lib/fetcher.ts
import { createFetcher } from "vovk"; import { useRegistry } from "@/registry"; export const fetcher = createFetcher({ transformResponse: (data) => { const state = useRegistry.getState(); state.parse(data); return data; }, });

On each RPC method call, the transformResponse function is invoked with the response data, which is then passed to the registry’s parse method.

import { UserRPC } from "vovk-client"; const users = await UserRPC.getUsers(); // transformResponse is called internally

This also works with React Query, where useQuery doesn’t require to read the data property anymore:

import { useQuery } from "@tanstack/react-query"; import { UserRPC } from "vovk-client"; // ... useQuery({ queryKey: UserRPC.getUsers.queryKey(), queryFn: () => UserRPC.getUsers(), }) // ... const users = useRegistry( useShallow((state) => userIds.map((id) => state.user[id])), );

Because our app also supports JSONLines responses for streaming data, we’re going to enhance the function a bit with another if check.

It’s also useful to have an option to bypass the registry for specific requests, so we’re going to add a bypassRegistry option to the fetcher config. It’s declared as a createFetcher generic parameter and used as an option in the second argument of transformResponse. It can be used as follows: await UserRPC.getUsers({ bypassRegistry: true }). You can extend this options object over time if needed.

src/lib/fetcher.ts
import { createFetcher, HttpStatus } from "vovk"; import useRegistry from "@/hooks/useRegistry"; export const fetcher = createFetcher<{ bypassRegistry?: boolean }>({ transformResponse: async (data, { bypassRegistry }) => { if (bypassRegistry) { return data; } const state = useRegistry.getState(); if ( data && typeof data === "object" && Symbol.asyncIterator in data && "onIterate" in data && typeof data.onIterate === "function" ) { data.onIterate(state.parse); // handle each item in the async iterable return data; } state.parse(data); // parse regular JSON data return data; }, onError: (error) => { if (error.statusCode === HttpStatus.UNAUTHORIZED) { document.location.href = "/login"; } }, });

The code above is fetched from GitHub repository. 

Declare the fetcher in the config. It replaces the default fetcher imported by the generated client.

vovk.config.mjs
// @ts-check /** @type {import('vovk').VovkConfig} */ const config = { outputConfig: { imports: { // ... fetcher: './src/lib/fetcher.ts', }, }, }; export default config;

That’s it. From now on, each request is processed by the registry’s parse method, and manual response handling is not required.

Last updated on