Gabb-c / pokenode-ts

A lightweight Node.js wrapper for the PokéAPI with built-in types.
https://pokenode-ts.vercel.app/
MIT License
244 stars 28 forks source link

Limit & offset not working on ListPokemon API using React Native #839

Closed minh-hd closed 1 year ago

minh-hd commented 1 year ago

What version of pokenode-ts are you using?

1.19.0

What version of Node.js are you using?

18.15.0

What operating system are you using?

macOS 13.3.1

Describe the Bug

I used ListPokemon() API using PokemonClient and it worked well without parameters. But when I passed in 2 params which are limit and offset, the result was exactly the same. And I found out that the problem only occurs when I use with React Native. It sent out a request looks like this: image

Here is the cURL that is created from the captured request:

curl -H "accept:application/json, text/plain, */*" -H "cache-control:no-cache" -H "pragma:no-cache" -H "expires:0" https://pokeapi.co/api/v2/pokemon?_searchParams%5B0%5D%5B0%5D=offset&_searchParams%5B0%5D%5B1%5D=80&_searchParams%5B1%5D%5B0%5D=limit&_searchParams%5B1%5D%5B1%5D=40

Expected Behavior

It should return a new list of pokemon with new offset and new limit

To Reproduce

  1. Initialize a react native project with this instruction
  2. Install this dependency following the instructions in README.md
  3. Using the pokemon client as below:
    const pokemonApi = new PokemonClient();
    const pokemonList = pokemonApi.listPokemons(20, 20);
minh-hd commented 1 year ago

Seems like there's a problem in my react native client

minh-hd commented 1 year ago

I tried create a vanilla Node.js project and used it and the dependency worked perfectly.

nartc commented 1 year ago

The problem might be axios-cache-interceptor is unable to invalidate the cache.

pokenode-ts constructs a URLSearchParams for { offset, limit } and URLSearchParams is interpreted differently on different environments (i.e: Node, Browsers etc...)

On the browser, URLSearchParams, specifically for { offset, limit }, is always an object with the value { size: 2 } (because there are 2 params offset and limit). Here's what I have to configure for cacheOptions to make listPokemons work on the browser

const cacheOptions = {
    generateKey: buildKeyGenerator((request) => {
        if (request.params) {
            return {
                method: request.method,
                url: request.url,
                params: request.params.toString(),
            };
        }
        return defaultKeyGenerator(request);
    }),
};
Gabb-c commented 1 year ago

@nartc I'm seeing that adding the URLSearchParams caused this issue. Maybe if we rollback this, the issue would be fixed.

Gabb-c commented 1 year ago

I reverted the usage of URLSearchParams and created a fn that builds the list url with the request params:

Pokemon Client

 /**
   * List Pokemons
   * @param offset The first item that you will get
   * @param limit How many Pokemons Stats per page
   * @returns A list of Pokemons
   */
  public async listPokemons(offset?: number, limit?: number): Promise<NamedAPIResourceList> {
    return new Promise<NamedAPIResourceList>((resolve, reject) => {
      const url = getListURL(Endpoints.POKEMON, offset, limit);
      this.api
        .get<NamedAPIResourceList>(url)
        .then((response: AxiosResponse<NamedAPIResourceList>) => resolve(response.data))
        .catch((error: AxiosError<string>) => reject(error));
    });
  }

Request Params

export const getListURL = (endpoint: Endpoints, offset?: number, limit?: number): string => {
  return `${endpoint}?offset=${offset ?? 0}&limit=${limit ?? 20}`;
};
nartc commented 1 year ago

I'll give this a try asap. Thanks Gabriel

Gabb-c commented 1 year ago

@minh-hd, @nartc Released in v1.19.1 Will leave the issue open for future discussions

minh-hd commented 1 year ago

@Gabb-c I put it to a test and it worked as I expected. Thank you 🙇🙇

Gabb-c commented 1 year ago

Happy to hear that @minh-hd! Thanks for effort @minh-hd and @nartc 🚀