gpt4 book ai didi

reactjs - 如何正确更改 RTK 查询中的响应数据?

转载 作者:行者123 更新时间:2023-12-05 04:39:08 25 4
gpt4 key购买 nike

我正在尝试在货币转换器应用程序中使用 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. 如果您的第二个查询取决于第一个查询的结果,在我的案例中使用“skip”或“skipToken”选项是正常做法吗?有没有更好的模式?
  2. 像我在 countriesAPI 中那样改变“transformResponse”中的数据,然后在 App 组件的 useFetchAllCountriesQuery 的“selectFromResult”选项中改变转换后的响应是正常的做法吗?有没有更好的模式?
  3. 在那种情况下,处理组件中的两个“isLoading”和两个“error”的好的模式是什么?

最佳答案

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

  1. 是的,总的来说没问题,但在您的情况下看起来并没有什么意义。如果 useFetchAllCountriesQuery 有查询参数,这是 useFetchAllCurrenciesQuery 结果的预期 - 听起来不错。如果这些结果在 selectFromResult 中使用 - 则不是这种情况。

  2. 同样 - 一般情况下没问题,但在您的情况下看起来使用错误。您可以在 transformResponse 之外执行所有这些转换,就在两个 Hook 调用之后。

  3. 有点取决于您稍后将如何使用它,但一般来说 - 只需添加新的 const 和 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);

...

error 对象也可以以某种方式聚合,这取决于您需要从中得到什么以及以什么顺序聚合。很可能您不需要将它们聚合在一起,只需显示错误状态,基于 isError 并分别记录两个错误对象。

最让我担心的,也是让定义正确的代码组合变得更加困难的是你在 transformResponse 部分中的 countriesAPI 定义,你在其中解析了该国家/地区内的所有货币.

我会说嵌套对象是一种糟糕的模式。在一组 id 或代码中将哪些货币“属于”该国家/地区的关系就足够了。或者像您使用 firstKey 那样仅使用第一个货币 ID,但不要将其解析为完整对象。 API 定义应仅与一个特定实体耦合。在您的情况下,这是国家/地区,因此它与货币无关。 (来自 SOLID 原则的“单一职责”和“接口(interface)隔离”——就是它们的意义所在)

顺便说一句,selectFromResult 在这里很有用,可以汇总用于国家/地区的所有货币,例如

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

稍后,您可以通过调用货币 API 来获取货币详细信息,但不是全部,而是您真正需要的 - 来自相关货币或一个国家的一个或多个 ID。

总体建议是移动这些货币和国家/地区获取、过滤和 isError | isLoading summing - 从 React 组件到一个单独的自定义钩子(Hook)中,它将只返回准备好的数据和组件实际将使用的标志。它会让事情变得非常清楚)

关于reactjs - 如何正确更改 RTK 查询中的响应数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70471696/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com