如何在React组件中通过RTK Query动态获取多数据集?
解决RTK Query动态获取多数据集的问题
针对你需要根据动态ID数组获取多份数据集的场景,有两种实用方案:
方案一:使用RTK Query的useQueries钩子
RTK Query内置的useQueries专门用于处理多个并行查询,完美绕过React Hooks不能在循环中调用的限制。
代码示例
import { useQueries } from '@reduxjs/toolkit/query/react'; import { devicesImportChartsApiSlice } from './path-to-your-api-slice'; const DeviceChart = ({ deviceIds, chartData }) => { // 为每个设备生成查询配置 const queryList = deviceIds.map(deviceId => ({ queryKey: ['deviceRecordList', { deviceId }], queryFn: async () => { // 调用现有endpoint获取数据并转换格式 const rawData = await devicesImportChartsApiSlice.endpoints.deviceRecordList .initiate({ deviceId }) .unwrap(); return rawData.map(record => ({ x: new Date(record.time_utc).getTime(), // 把UTC时间转成时间戳 y: record.value })); }, skip: !chartData // 保持原有的跳过逻辑 })); // 执行所有查询 const queryResults = useQueries({ queries: queryList }); // 整理成ChartJS需要的格式:过滤成功返回的数据 const formattedDatasets = queryResults .filter(result => result.isSuccess && result.data) .map(result => result.data); // 渲染ChartJS组件(示例) return ( <div> {queryResults.some(r => r.isLoading) && <p>加载中...</p>} {queryResults.some(r => r.isError) && <p>加载失败</p>} {formattedDatasets.length > 0 && ( <Chart data={{ datasets: formattedDatasets.map((data, idx) => ({ data, label: `设备${deviceIds[idx]}`, borderColor: `hsl(${idx * 60}, 70%, 50%)` })) }} /> )} </div> ); };
方案二:创建批量查询端点(性能更优)
如果后端支持批量接口,推荐直接新增一个批量获取设备记录的endpoint,减少HTTP请求数,提升性能。
步骤1:扩展API切片
import { citywebApi } from "../../openapi/citywebApi" import { processError } from "../../utils/errors" export const devicesImportChartsApiSlice = citywebApi.enhanceEndpoints({ addTagTypes: ['devicesImport'], endpoints: (build) => ({ deviceRecordList: { async onQueryStarted(_, { dispatch, queryFulfilled }) { try { await queryFulfilled } catch(error) { processError(error, dispatch, 'err msg') } }, providesTags: ['devicesImport'] }, // 新增批量查询端点 batchDeviceRecordList: build.query({ query: (deviceIds) => ({ url: `/api/device_record/list/batch`, method: 'POST', body: { deviceIds } // 传给后端的设备ID数组 }), // 自动转换返回数据为目标格式 transformResponse: (response) => { // 假设后端返回格式为 { [deviceId]: DeviceRecord[] } return Object.values(response).map(records => records.map(record => ({ x: new Date(record.time_utc).getTime(), y: record.value })) ); }, async onQueryStarted(_, { dispatch, queryFulfilled }) { try { await queryFulfilled } catch(error) { processError(error, dispatch, '批量获取设备记录失败') } }, providesTags: ['devicesImport'] }) }) }) export const { useDeviceRecordListQuery, useBatchDeviceRecordListQuery } = devicesImportChartsApiSlice
步骤2:组件中使用批量查询
const DeviceChart = ({ deviceIds, chartData }) => { const { data: formattedDatasets, isLoading, isError } = useBatchDeviceRecordListQuery(deviceIds, { skip: !chartData || deviceIds.length === 0 }); return ( <div> {isLoading && <p>加载中...</p>} {isError && <p>加载失败</p>} {formattedDatasets && formattedDatasets.length > 0 && ( <Chart data={{ datasets: formattedDatasets.map((data, idx) => ({ data, label: `设备${deviceIds[idx]}`, borderColor: `hsl(${idx * 60}, 70%, 50%)` })) }} /> )} </div> ); };
注意事项
- 方案二中需要后端配合实现批量接口,如果后端暂不支持,优先使用方案一。
- 数据转换时注意
time_utc的格式,确保能正确转换为时间戳。 - 处理加载、错误状态,提升用户体验。
内容的提问来源于stack exchange,提问作者koubin
相关产品推荐
相关产品推荐

