ecyrbe / zodios-react

React hooks for zodios
MIT License
64 stars 12 forks source link

useQuery generated key is not equal to getKeyBy[...] result, when config is undefined #306

Closed ryuina closed 1 year ago

ryuina commented 1 year ago

Hi, I'm using zodios-react hooks with a lot of joy, it is really helpful and type-safe. I don't need to waist more time to make hooks :) But I found an unexpected result about the generated key.

The problem happens when I call a query without any configs like hooks.useGetUsers(). But the query key is not equal to hooks.getKeyByAlias('getUsers'), so I couldn't invalidate that query if I want to call and update in different pages (because I cannot use invalidate() method from the useQuery result).

What I wanted from source code: hooks.spec.tsx

it ("should match generated useQuery key with getKey result", async () => {
    const { result, waitFor } = renderHook(
      () => apiHooks.useGet("/users"),
      { wrapper }
    );
    await waitFor(() => result.current.isSuccess);
    expect(result.current.key).toEqual(apiHooks.getKeyByPath("get", "/users"));
  })

hooks.ts

getKeyBy[...]<...>(
  ...
) {
    const endpoint = this.getEndpointByPath(method, path);
    if (!endpoint) {
      throw new Error(`No endpoint found for path '${method} ${path}'`);
    }
    const params = pick(config as AnyZodiosMethodOptions | undefined, [
      "params",
      "queries",
    ]);
    return [{ api: this.apiName, path: endpoint.path }, params] as QueryKey;
  }

It's because the pick() function always returns an object even a config is undefined, therefore queryResult.key is set like this [{api: '...', path: '...'}, {}].

If pick() returns an object every time, the result of the useQuery key also should be always length two.

But the functions getKeyByPath and getKeyByAlias still return length 1 array when the config is undefined.

In this case, useQuery without any params or configs, we cannot invalidate that query because the key, generated, announced to queryClient is not equal to getKeyBy...() result.

(Anyway, if I were you, I'll fix pick() to return undefined when config is empty to make the QueryKey more clean)

ryuina commented 1 year ago

Oh I found queryClient.invalidateQuery() is still working even useQuery key array has one more empty object. So the issue above is not a bug. 😢 So I close this issue, but can you consider this issue for consistency? I think it will be better if useQuery key is equal to getKeyBy... result

ecyrbe commented 1 year ago

As the docs states this is on purpose, to invalide a wider range of keys. But i see the point. An option to customise behaviour will be a solution. This is already tracked on another issue