如何在RTK查询中正确更改响应数据



我正在尝试在货币转换器应用程序中使用RTK查询。此应用程序基于2 API。

首先,我要获取一个带有货币的对象。然后,我获取一系列国家并对其进行过滤,这取决于该国是否拥有这种货币。

存储代码:

export const store = configureStore({
reducer: {
[currenciesAPI.reducerPath]: currenciesAPI.reducer,
[countriesAPI.reducerPath]: countriesAPI.reducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(currenciesAPI.middleware, countriesAPI.middleware)
})

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
}
})
})
})

组件代码:

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
})
...

问题:

  1. 使用";跳过";或";skipToken";选项,如果您的第二个查询取决于第一个查询的结果?有更好的模式吗
  2. 在";transformResponse";就像我在国家API中所做的那样,然后在";selectFromResult;在应用程序组件中使用FetchAllCountrysQuery中的选项?有更好的模式吗
  3. 什么是一个好的模式来处理两个";isLoading;和两个";错误";在这种情况下的组件中

我可以看到更多的陷阱,但要回答以下问题:

  1. 是的,一般来说还可以,但在您的情况下看起来并没有真正的意义。如果useFetchAllCountriesQuery有查询参数,这是useFetchAllCurrenciesQuery结果中所期望的-听起来不错。如果这些结果在selectFromResult中使用-情况并非如此。

  2. 再说一遍,它总体上是可以的,但在你的情况下似乎用错了方法。所有这些转换都可以在两个钩子调用之后从transformResponse中执行。

  3. 这在一定程度上取决于您以后将如何使用它,但一般来说,只需添加带有sum:的新常量即可

    const isLoading = currenciesIsLoading || countriesIsLoading;
    

并在UI中使用它。

总结一下,我会这样做:

const getCountriesWithCurrency = (currencies, countries) => {
if (currencies && countries )  {
return countries?.filter(country => currenciesData && 
currencies[country.currencyShortName])
}
}
const App: React.FC = () => {
const { 
data: currenciesData, 
error: currenciesError, 
isError: currenciesIsError,
isLoading: currenciesIsLoading 
} = useFetchAllCurrenciesQuery()
const { 
data: countriesData, 
error: countriesError, 
isError: countriesIsError,
isLoading: countriesIsLoading
} = useFetchAllCountriesQuery()
const isLoading = currenciesIsLoading || countriesIsLoading;
const isError = currenciesIsError || countriesIsError;
const countries = getCountriesWithCurrency(currenciesData, countriesData);
...

错误对象也可以以某种方式聚合,这取决于您对它的需求以及顺序。很可能您不需要聚合它们,只需根据isError显示错误状态,并分别记录这两个错误对象。

最让我担心的是,让我更难定义正确的代码组合的是transformResponse部分中的countriesAPI定义,在这里你可以解析国内的所有货币。

我认为嵌套对象是一种糟糕的模式。只要有一个关系就足够了;属于";在一系列id或代码中指向国家。或者像使用firstKey一样只使用第一个货币id,但不要将其解析为完整对象。API定义应仅与一个特定实体耦合。在你的情况下,这是一个国家,所以它应该与货币无关。

顺便说一句,selectFromResult在这里很有用,可以汇总各国使用的所有货币,比如

selectFromResult: ({ data, error, isLoading }) => ({
data,
error,
isLoading,
relatedCurrencies:  data?.reduce((acc, country) => ([...acc, ...Object.keys(country.currencies)]), [])
}),

稍后,您可以通过调用货币API来获取货币详细信息,但不是所有这些信息,而是您真正需要的信息-针对相关货币中的一个或多个id,或针对一个国家。

总体建议是将这些货币和国家/地区的提取、过滤和isError|isLoading suming-out of react组件转移到一个单独的自定义挂钩中,该挂钩将只返回一个准备好的数据和标记,该组件将实际使用这些数据和标记。它会让它变得非常清楚(

相关内容

  • 没有找到相关文章

最新更新