T
TanStack3y ago
like-gold

v5 issue

Hi there, I have a followig hook:
import { queryKeys } from "@/app/constants/queryKeys";
import { CURRENCIES_API } from "@/config/api";
import { CurrencyOption } from "@/src/currencyStore";
import { useQuery } from "@tanstack/react-query";
import { toast } from "react-hot-toast";

type CurrencyData = {
[currencyCode: string]: string | number;
};

export const useFetchCurrenciesQuery = () => {
const getCurrencyDataFn = async () => {
const response = await fetch(CURRENCIES_API);
const result: CurrencyData = await response.json();
return result;
};


return useQuery<CurrencyData, Error>({
queryKey: [queryKeys.currencies],
queryFn: getCurrencyDataFn,
select: (data) => {
if (!data) return [];

return Object.entries(data.data).map(([label, value]) => ({
label,
value,
}));
},
onSuccess: () => {
toast.success("Fetched data successfully");
},
onError: (error: unknown) =>
toast.error(`Something went wrong: ${error}`),
});
};
import { queryKeys } from "@/app/constants/queryKeys";
import { CURRENCIES_API } from "@/config/api";
import { CurrencyOption } from "@/src/currencyStore";
import { useQuery } from "@tanstack/react-query";
import { toast } from "react-hot-toast";

type CurrencyData = {
[currencyCode: string]: string | number;
};

export const useFetchCurrenciesQuery = () => {
const getCurrencyDataFn = async () => {
const response = await fetch(CURRENCIES_API);
const result: CurrencyData = await response.json();
return result;
};


return useQuery<CurrencyData, Error>({
queryKey: [queryKeys.currencies],
queryFn: getCurrencyDataFn,
select: (data) => {
if (!data) return [];

return Object.entries(data.data).map(([label, value]) => ({
label,
value,
}));
},
onSuccess: () => {
toast.success("Fetched data successfully");
},
onError: (error: unknown) =>
toast.error(`Something went wrong: ${error}`),
});
};
no matter what i do there is a TS error: Type '(data: CurrencyData) => { label: string; value: any; }[]' is not assignable to type '(data: CurrencyData) => CurrencyData'.ts(2769) queryClient-13f81fcb.d.ts(415, 5): The expected type comes from property 'select' which is declared here on type 'UndefinedInitialDataOptions<CurrencyData, Error, CurrencyData, QueryKey>' queryClient-13f81fcb.d.ts(415, 5): The expected type comes from property 'select' which is declared here on type 'DefinedInitialDataOptions<CurrencyData, Error, CurrencyData, QueryKey>' queryClient-13f81fcb.d.ts(415, 5): The expected type comes from property 'select' which is declared here on type 'UseQueryOptions<CurrencyData, Error, CurrencyData, QueryKey>' Is this smth with implementation? v3 did not give me that errors... how can i fix it?
13 Replies
ratty-blush
ratty-blush3y ago
Pretty sure you can just let useQuery infer, but onSuccess and onError are removed in v5. https://tkdodo.eu/blog/breaking-react-querys-api-on-purpose
Breaking React Query's API on purpose
Why good API design matters, even if it means breaking existing APIs in the face of resistance.
like-gold
like-goldOP3y ago
Ok, yeah well explained, only thing i could not find was how to refactor data returned, so far used to work with select, how shall i handle that in v5
select: (data) => {
if (!data) return [];

return Object.entries(data.data).map(([label, value]) => ({
label,
value,
}));
},
select: (data) => {
if (!data) return [];

return Object.entries(data.data).map(([label, value]) => ({
label,
value,
}));
},
ratty-blush
ratty-blush3y ago
Not sure, I think select remained relatively unchanged
ratty-blush
ratty-blush3y ago
Dominik wrote this blog about data transformations if it helps https://tkdodo.eu/blog/react-query-data-transformations
React Query Data Transformations
Learn the possibilities to perform the quite common and important task of transforming your data with react-query
like-gold
like-goldOP3y ago
no it did not... there is an error:
No description
like-gold
like-goldOP3y ago
Sorry, my bad... i typed in a wrong way, last thing: again comming back to my hook which works now:
import { queryKeys } from "@/app/constants/queryKeys";
import { CURRENCIES_API } from "@/config/api";
import { useQuery } from "@tanstack/react-query";
import { useEffect } from "react";
import { toast } from "react-hot-toast";

type ExchangeRates = {
data: {
[currencyCode: string]: number;
};
};
export const useFetchCurrenciesQuery = () => {
const getCurrencyDataFn = async () => {
const response = await fetch(CURRENCIES_API);
const result: ExchangeRates = await response.json();
return result.data;
};

const currencies = useQuery({
queryKey: [queryKeys.currencies],
queryFn: getCurrencyDataFn,
select: (data) => {
if (!data) return [];
return Object.entries(data).map(([label, value]) => ({
label,
value,
}));
},
});

useEffect(() => {
if (currencies.error) {
toast.error("Something went wrong");
}
}, [currencies.error]);

useEffect(() => {
if (currencies.data) {
toast.success("Fetched data successfully");
}
}, [currencies.data]);

return {
currencies,
};
};
import { queryKeys } from "@/app/constants/queryKeys";
import { CURRENCIES_API } from "@/config/api";
import { useQuery } from "@tanstack/react-query";
import { useEffect } from "react";
import { toast } from "react-hot-toast";

type ExchangeRates = {
data: {
[currencyCode: string]: number;
};
};
export const useFetchCurrenciesQuery = () => {
const getCurrencyDataFn = async () => {
const response = await fetch(CURRENCIES_API);
const result: ExchangeRates = await response.json();
return result.data;
};

const currencies = useQuery({
queryKey: [queryKeys.currencies],
queryFn: getCurrencyDataFn,
select: (data) => {
if (!data) return [];
return Object.entries(data).map(([label, value]) => ({
label,
value,
}));
},
});

useEffect(() => {
if (currencies.error) {
toast.error("Something went wrong");
}
}, [currencies.error]);

useEffect(() => {
if (currencies.data) {
toast.success("Fetched data successfully");
}
}, [currencies.data]);

return {
currencies,
};
};
how can show loader ? i am not sure how to get access to isLoading, isFetching etc?
ratty-blush
ratty-blush3y ago
They'd all be on your currencies variable
like-gold
like-goldOP3y ago
sorry to be a pain but not sure about it, i mean i can to smth like
const {isLoading, data: currencies} = useQuery({ but when i do that i am getting errors here
const {isLoading, data: currencies} = useQuery({ but when i do that i am getting errors here
useEffect(() => { if (currencies.error) { toast.error("Something went wrong"); } }, [currencies.error]);```
ratty-blush
ratty-blush3y ago
Doing it that way turns currencies into just your data, not the entire useQuery result. You can either do what you had as currencies.isFetching or destruct all the variables you want:
const { isFetching, error, data: currencies } = useQuery({
...
})
const { isFetching, error, data: currencies } = useQuery({
...
})
like-gold
like-goldOP3y ago
Mint! all works, massive thank you @troywoy just wondering would u know when would be the best time to set currencies to Zustand store? I am using Next.js and checking some possible options
ratty-blush
ratty-blush3y ago
The first link I sent you should give you some ideas on approaches to take
like-gold
like-goldOP3y ago
great! will have a look, and the last thing: how can i set refresh data every 24 hours? Shall i set stale?
ratty-blush
ratty-blush3y ago
Yeah staleTime should work

Did you find this page helpful?