同一组件使用多个RTK Query查询的渲染异常问题
问题解答
同一个组件里能不能用多个RTK Query查询?
完全可以,组件里调用多少个RTK Query生成的hook都没有限制。你现在遇到的「搜索请求能拿到数据但页面还是显示全量列表」的问题,和多查询调用本身没关系,核心问题是你没根据当前的搜索/筛选状态选择对应数据源——大概率是写渲染逻辑的时候,一直固定取全量国家查询返回的data,就算按名称搜索的hook已经拿到了正确结果,这份数据根本没被用到渲染里。
怎么调整代码对齐原有useEffect版本的筛选效果
你之前用useEffect写的逻辑本质是:根据当前搜索词、地区筛选条件动态切换请求接口,拿到对应接口的返回结果后统一渲染。用RTK Query实现的时候没必要硬拆成多个独立查询再手动切数据源,更简洁也更符合RTK Query设计思路的写法是:根据当前状态动态传查询参数,配合skip参数控制无效请求,统一拿当前激活查询的返回值渲染,还能自动用上RTK Query的缓存能力,切回之前的筛选条件不用重复发请求。
具体改法
- 先把三个接口的逻辑合并成一个支持动态传参的查询端点就行,不用拆成多个独立查询:
// countries 接口定义文件 import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' export const countriesApi = createApi({ reducerPath: 'countriesApi', baseQuery: fetchBaseQuery({ baseUrl: 'https://restcountries.com/v3.1/' }), endpoints: (builder) => ({ getCountries: builder.query({ query: ({ type, payload }) => { switch(type) { case 'searchByName': return `name/${encodeURI(payload)}?fullText=true` case 'filterByRegion': return `region/${payload}` default: return 'all' } } }) }) }) export const { useGetCountriesQuery } = countriesApi
- 组件里只需要维护搜索词、选中地区两个状态,根据状态计算当前查询参数,直接拿hook返回的data、error、加载状态渲染即可,逻辑和你原来的useEffect版本完全对齐:
export const ListOfCountries = () => { const [searchQuery, setSearchQuery] = useState("") const [selectedRegion, setSelectedRegion] = useState("") // 根据当前状态计算要传的查询参数 const queryArg = useMemo(() => { if (searchQuery.trim()) { return { type: 'searchByName', payload: searchQuery.trim() } } if (selectedRegion) { return { type: 'filterByRegion', payload: selectedRegion } } return { type: 'all' } }, [searchQuery, selectedRegion]) // 参数变化时RTK Query会自动发请求,自动缓存结果 const { data, error, isFetching } = useGetCountriesQuery(queryArg) return ( <> <Flex> <Input type="search" placeholder="Search for a country..." onChange={useDebounce((e) => setSearchQuery(e.target.value), 700)} /> <FilterBox setSelectedRegion={setSelectedRegion} /> </Flex> <Flex> {isFetching && <p>加载中...</p>} {error && !isFetching && <p>{searchQuery} 未找到,请输入国家全称</p>} {!error && !isFetching && data?.map((item) => ( <Link to={`/country/${item.cca3}`} key={item.cca3}> <PreviewCard item={item} /> </Link> ))} </Flex> </> ) }
如果你坚持保留原来拆分多个查询端点的写法也可以,就是要多写点判断逻辑:根据当前搜索、筛选状态,决定要取哪个查询hook返回的data,同时给非当前激活的查询加上skip: true避免发多余请求。这种写法冗余度高,后续加新筛选条件还要改判断逻辑,不推荐。
额外提一句:列表渲染的key别用数组index,直接用国家数据里自带的唯一标识
cca3,不然筛选、排序的时候容易出现组件渲染错乱的问题。
内容的提问来源于stack exchange,提问作者Aroyan
相关产品推荐
相关产品推荐

