I was following a tutorial and was using the exact same code but because of a different dependency version, I get an error.
The Tutorial dependency version:
"jotai": "^1.9.0",
"jotai-tanstack-query": "^0.4.0",
My dependency version:
"jotai": "^2.1.0",
"jotai-tanstack-query": "^0.7.0",
The code:
import { atom } from "jotai";
import { atomsWithQuery } from "jotai-tanstack-query";
export interface Pokemon {
id: number;
name: string;
type: string[];
hp: number;
attack: number;
defense: number;
special_attack: number;
special_defense: number;
speed: number;
}
export const searchAtom = atom("");
const [allPokemon] = atomsWithQuery<Pokemon[]>(() => ({
queryKey: ["pokemon"],
queryFn: async () => {
const res = await fetch("/pokemon.json");
return res.json();
}
}));
export const pokemonAtom = atom((get) => {
const search = get(searchAtom).toLowerCase();
const all = get(allPokemon);
return all.filter((p) => p.name.toLowerCase().includes(search)); // Error
});
I get error: Property 'filter' does not exist on type 'Pokemon[] | Promise<Pokemon[]>'. Property 'filter' does not exist on type 'Promise<Pokemon[]>'.ts(2339)
It appears atomsWithQuery will also return a promise in the newer version. (Type of allPokemon
in old version: Pokemon[]
, new version Pokemon[] | Promise<Pokemon[]>
) How can I avoid/fix this error? Thank you
The type tells you that get(allPokemon)
might return an array
or a Promise
that resolves to an array
. So what you should be able to do is await
the response, then you can be sure that it's an array
and not a promise. Then the type error should disappear, because it knows that the returned data is an array
- then it knows that it has the filter()
function.
export const pokemonAtom = atom(async (get) => {
const search = get(searchAtom).toLowerCase();
const all = await get(allPokemon);
return all .filter((p) => p.name.toLowerCase().includes(search));
});
EDIT
Another way is to use the useAtom
instead of get
that will resolve it for you. Then you don't need to make your function asyncronious.
export const pokemonAtom = atom((get) => {
const search = get(searchAtom).toLowerCase();
const [all] = useAtom(allPokemon)
return all.filter((p) => p.name.toLowerCase().includes(search)); // Error
});