I'm trying to use RTK Query in currency-converter app. This app is based on 2 API.
First, I'm fetching an object with currencies. Then, I'm fetching an array of countries and filter it, depending whether the country has that kind of currency or not.
Code fo store:
export const store = configureStore({
reducer: {
[currenciesAPI.reducerPath]: currenciesAPI.reducer,
[countriesAPI.reducerPath]: countriesAPI.reducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(currenciesAPI.middleware, countriesAPI.middleware)
})
Code for API:
export const currenciesAPI = createApi({
reducerPath: 'currenciesAPI',
baseQuery: fetchBaseQuery({ baseUrl: 'https://api.frankfurter.app'}),
endpoints: (build) => ({
fetchAllCurrencies: build.query<Currencies, void>({
query: () => ({
url: '/currencies'
}),
})
})
})
export const countriesAPI = createApi({
reducerPath: 'countriesAPI',
//tagTypes: ['Country'],
baseQuery: fetchBaseQuery({ baseUrl: 'https://restcountries.com/v3.1'}),
endpoints: (build) => ({
fetchAllCountries: build.query<TransformedCountries[], string>({
query: () => ({
url: '/all'
}),
transformResponse: (response: Countries[]) : TransformedCountries[] => {
const countriesWithCurrency = response.filter((country: Countries) => country.currencies) // <-- MUTATING DATA HERE AND BELOW IS NORMAL?
const transformedCountriesArray = countriesWithCurrency.map((item: Countries) => {
const keys = Object.keys(item.currencies)
const firstKey = keys[0]
return {
name: item.name.common,
currencyFullName: item.currencies[firstKey].name,
currencyShortName: firstKey,
currencySymbol: item.currencies[firstKey].symbol,
flag: item.flags.svg
}
})
const finalCountriesArray = transformedCountriesArray.sort((a: TransformedCountries, b: TransformedCountries) => (a.name > b.name) ? 1 : (a.name < b.name) ? -1 : 0)
return finalCountriesArray
}
})
})
})
Code for component:
const App: React.FC = () => {
const {
data: currenciesData,
error: currenciesError,
isLoading: currenciesIsLoading
} = useFetchAllCurrenciesQuery()
const {
data: countriesData,
error: countriesError,
isLoading: countriesIsLoading
} = useFetchAllCountriesQuery('', {
selectFromResult: ({ data, error, isLoading }) => ({
data: data?.filter((country: TransformedCountries) => currenciesData && currenciesData[country.currencyShortName]), // <-- MUTATING DATA HERE AND BELOW IS NORMAL?
error,
isLoading
}),
skip: !currenciesData
})
...
Questions:
- Is it normal practise to use "skip" or "skipToken" option in my case if your second query depends on the result of the first? Is there any better pattern?
- Is it normal practise to mutate data in "transformResponse" like I did in countriesAPI and then mutate transformed response in "selectFromResult" option in useFetchAllCountriesQuery in App component? Is there any better pattern?
- What is a good pattern to handle two "isLoading" and two "error" in a component in that case?