rgd*_*dzv 6 reactjs redux react-redux redux-toolkit rtk-query
我正在尝试在货币转换器应用程序中使用 RTK 查询。这个应用程序是基于2个API。
首先,我正在获取一个带有货币的对象。然后,我获取一系列国家/地区并对其进行过滤,具体取决于该国家/地区是否拥有该种货币。
商店代码:
export const store = configureStore({
reducer: {
[currenciesAPI.reducerPath]: currenciesAPI.reducer,
[countriesAPI.reducerPath]: countriesAPI.reducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(currenciesAPI.middleware, countriesAPI.middleware)
})
Run Code Online (Sandbox Code Playgroud)
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
}
})
})
})
Run Code Online (Sandbox Code Playgroud)
组件代码:
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
})
...
Run Code Online (Sandbox Code Playgroud)
问题:
我还可以看到更多陷阱,但回答以下问题:
是的,一般来说没问题,但对于你的情况来说看起来并没有多大意义。如果useFetchAllCountriesQuery有查询参数,这是从useFetchAllCurrenciesQuery结果中预期的 - 听起来不错。如果这些结果被用于selectFromResult- 情况就不是这样了。
再说一次 - 一般来说是可以的,但在你的情况下看起来使用方式错误。所有这些转换都可以transformResponse在两个钩子调用之后执行 OUT of 。
有点取决于您稍后将如何使用它,但一般来说 - 只需添加带有 sum 的 new const 即可:
const isLoading = currenciesIsLoading || countriesIsLoading;
Run Code Online (Sandbox Code Playgroud)
并在 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);
...
Run Code Online (Sandbox Code Playgroud)
错误对象也可以以某种方式聚合,具体取决于您需要的内容以及顺序。您很可能不需要聚合它们,只需根据 isError 显示错误状态并分别记录两个错误对象。
最让我担心的,也是让定义正确的代码组合变得更加困难的是,您的countriesAPI定义transformResponse部分解决了国内所有货币的问题。
我想说,嵌套对象是一个不好的模式。在一系列 ID 或代码中了解哪些货币“属于”该国家就足够了。或者只使用第一个货币 ID,就像您使用firstKey 所做的那样,但不将其解析为完整对象。API 定义应该仅与一个特定实体耦合。你的情况是国家,所以它应该与货币无关。(SOLID 原则中的“单一职责”和“接口隔离”——这就是它们的含义)
顺便说一句,selectFromResult这里很有用,可以汇总国家/地区使用的所有货币,例如
selectFromResult: ({ data, error, isLoading }) => ({
data,
error,
isLoading,
relatedCurrencies: data?.reduce((acc, country) => ([...acc, ...Object.keys(country.currencies)]), [])
}),
Run Code Online (Sandbox Code Playgroud)
稍后,您可以通过调用货币 API 来获取货币详细信息,但不是全部,而是您真正需要的 - 相关货币的一个或多个 id,或一个国家/地区。
总体建议 - 是移动这些货币和国家的获取、过滤和 isError | isLoading summing - 将反应组件放入一个单独的自定义钩子中,该钩子将仅返回准备好的数据和组件实际将使用的标志。这会让事情变得很清楚)
| 归档时间: |
|
| 查看次数: |
5088 次 |
| 最近记录: |