React中如何渲染useEffect返回的数据?附代码示例
解决React中渲染Cube.js查询数据的问题
看起来你已经成功通过fetch获取到了Cube API返回的数据,但还没把这些数据和你的图表组件关联起来。我帮你梳理下怎么修改代码,把拿到的数据渲染出来:
步骤1:添加状态管理存储查询数据
首先,你需要用React的useState来存储fetch回来的数据,让组件能感知到数据变化并触发重新渲染:
import { useState, useEffect, useMemo } from 'react'; const ChartRenderer = ({ vizState }) => { // 新增状态存储查询结果、加载状态和错误信息 const [chartData, setChartData] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); let ur = encodeURIComponent(JSON.stringify(vizState.query)); let u = "http://localhost:4000/cubejs-api/v1/sql?query=" + ur; console.log(u) useEffect(() => { // 过滤空查询请求 if(u === "http://localhost:4000/cubejs-api/v1/sql?query=undefined") return; // 请求开始时更新状态 setLoading(true); setError(null); fetch(u) .then(response => { if (!response.ok) throw new Error('数据请求失败'); return response.json(); }) .then(data => { // 将获取到的原始数据存入状态 setChartData(data); }) .catch(err => { setError(err.message); }) .finally(() => { setLoading(false); }); },[u]);
步骤2:转换数据适配图表组件格式
Cube.js的/sql接口返回的是原始数据库查询结果,你需要把它转换成图表组件需要的结构(比如折线图/柱状图需要的labels和datasets):
// 用useMemo缓存转换后的数据,避免不必要的重计算 const transformedData = useMemo(() => { if (!chartData) return null; // 假设返回的data是查询结果数组,结构类似: // [{line_items__created_at_day: "2024-01-01", line_items__count: 10}, ...] return { labels: chartData.map(item => item.line_items__created_at_day), datasets: [{ label: '每日订单数量', data: chartData.map(item => item.line_items__count), borderColor: '#1976d2', fill: false }] }; }, [chartData]);
步骤3:替换渲染逻辑,使用自定义数据
原来的代码里同时用了fetch和useCubeQuery,这会造成逻辑重复。如果你想自己控制数据请求,就替换掉useCubeQuery的逻辑,直接把转换后的数据传给图表组件:
const { chartType, pivotConfig } = vizState; const component = TypeToMemoChartComponent[chartType]; // 处理加载、错误和空数据的状态提示 if (loading) return <div>数据加载中...</div>; if (error) return <div>加载出错:{error}</div>; if (!chartData || !transformedData) return <div>暂无数据</div>; // 将转换后的数据传入图表组件 return component && renderChart(component)({ data: transformedData, pivotConfig, // 按需添加图表组件需要的其他props }); };
额外优化:直接使用Cube.js官方hooks简化代码
其实你可以不用自己写fetch,Cube.js提供的useCubeQuery已经帮你封装了数据请求、缓存、状态管理等逻辑,用它会更简洁:
import { useCubeQuery } from '@cubejs-client/react'; const ChartRenderer = ({ vizState }) => { const { query, chartType, pivotConfig } = vizState; const component = TypeToMemoChartComponent[chartType]; // useCubeQuery自动处理数据请求,返回加载、错误、结果集等状态 const { loading, error, resultSet } = useCubeQuery(query); if (loading) return <div>数据加载中...</div>; if (error) return <div>加载出错:{error.message}</div>; if (!resultSet) return <div>暂无数据</div>; // 用resultSet的内置方法转换数据 const transformedData = { labels: resultSet.categories().map(c => c.title), datasets: resultSet.series().map(s => ({ label: s.title, data: s.values })) }; return component && renderChart(component)({ data: transformedData, pivotConfig }); };
内容的提问来源于stack exchange,提问作者anushka




