You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 13:03:16