自定义VictoryBlock组件在VictoryChart中使用时报Array.from类型错误
问题:VictoryChart中使用自定义组件报错"TypeError: Array.from requires an array-like object - not null or undefined"
我尝试在VictoryChart组件中使用自定义的VictoryBlock组件时,出现错误:"TypeError: Array.from requires an array-like object - not null or undefined"。但直接在VictoryChart中编写VictoryArea和VictoryScatter的代码时,功能完全正常,求解决办法。
VictoryBlock.js
function VictoryBlock({ data, fill, stroke }) { return ( <> <VictoryArea data={data} interpolation="natural" style={{ data: { fill: fill, fillOpacity: 0.7, stroke: stroke, strokeWidth: 2, }, }} /> <VictoryScatter style={{ data: { fill: stroke } }} size={5} labels={({ datum }) => datum.y} //check this labelComponent={<VictoryTooltip renderInPortal={false} />} //check this data={data} /> </> ); } export default VictoryBlock;
未拆分组件时可正常运行的VictoryDemo.js
function VictoryDemo({ firstData, secondData, thirdData }) { return ( <VictoryChart animate={{ easing: "elastic", duration: 2000 }} // gives performance problem theme={VictoryTheme.material} /* containerComponent={ <VictoryZoomContainer zoomDomain={{ x: [0, 6], y: [0, 15] }} /> // gives performance problem } */ > <VictoryArea data={firstData} interpolation="natural" style={{ data: { fill: "#CACACA", fillOpacity: 0.7, stroke: "black", strokeWidth: 2, }, }} /> <VictoryScatter style={{ data: { fill: "black" } }} size={5} labels={({ datum }) => datum.y} //check this labelComponent={<VictoryTooltip renderInPortal={false} />} //check this data={firstData} /> <VictoryArea data={secondData} interpolation="natural" style={{ data: { fill: "#A2A2A2", fillOpacity: 0.7, stroke: "black", strokeWidth: 2, }, }} /> <VictoryScatter style={{ data: { fill: "black" } }} size={5} labels={({ datum }) => datum.y} //check this labelComponent={<VictoryTooltip renderInPortal={false} />} //check this data={secondData} /> <VictoryArea data={thirdData} interpolation="natural" style={{ data: { fill: "#6F6D6D", fillOpacity: 0.7, stroke: "black", strokeWidth: 2, }, }} /> <VictoryScatter style={{ data: { fill: "black" } }} size={5} labels={({ datum }) => datum.y} //check this labelComponent={<VictoryTooltip renderInPortal={false} />} //check this data={thirdData} /> </VictoryChart> ); } export default VictoryDemo;
拆分组件后无法运行的VictoryDemo.js
function VictoryDemo({ firstData, secondData, thirdData }) { return ( <VictoryChart animate={{ easing: "elastic", duration: 2000 }} // gives performance problem theme={VictoryTheme.material} /* containerComponent={ <VictoryZoomContainer zoomDomain={{ x: [0, 6], y: [0, 15] }} /> // gives performance problem } */ > <VictoryBlock data={firstData} fill="#CACACA" stroke="black" /> <VictoryBlock data={secondData} fill="#A2A2A2" stroke="black" /> <VictoryBlock data={thirdData} fill="#6F6D6D" stroke="black" /> </VictoryChart> ); } export default VictoryDemo;
解决办法
核心原因是VictoryChart只能直接识别Victory系列的可视化组件(如VictoryArea、VictoryScatter),而你用React.Fragment(<>)包裹两个组件后,VictoryChart无法穿透Fragment识别内部的子组件,导致内部处理逻辑尝试对null/undefined值执行Array.from,触发报错。
有两种可行的修复方案:
方案1:返回元素数组
直接让VictoryBlock返回一个包含VictoryArea和VictoryScatter的数组,React允许组件返回元素数组,VictoryChart能正确识别数组中的每个Victory组件:
function VictoryBlock({ data, fill, stroke }) { return [ <VictoryArea key="area" data={data} interpolation="natural" style={{ data: { fill: fill, fillOpacity: 0.7, stroke: stroke, strokeWidth: 2, }, }} />, <VictoryScatter key="scatter" style={{ data: { fill: stroke } }} size={5} labels={({ datum }) => datum.y} labelComponent={<VictoryTooltip renderInPortal={false} />} data={data} /> ]; } export default VictoryBlock;
注意要给数组中的每个元素添加唯一key,符合React的列表渲染要求。
方案2:使用VictoryGroup包裹
VictoryGroup是Victory官方提供的组件容器,专门用于组合多个Victory可视化组件,VictoryChart能直接识别VictoryGroup:
import { VictoryGroup } from "victory"; function VictoryBlock({ data, fill, stroke }) { return ( <VictoryGroup> <VictoryArea data={data} interpolation="natural" style={{ data: { fill: fill, fillOpacity: 0.7, stroke: stroke, strokeWidth: 2, }, }} /> <VictoryScatter style={{ data: { fill: stroke } }} size={5} labels={({ datum }) => datum.y} labelComponent={<VictoryTooltip renderInPortal={false} />} data={data} /> </VictoryGroup> ); } export default VictoryBlock;
两种方案都能解决报错问题,推荐使用方案2,因为VictoryGroup还提供了统一配置子组件的能力,扩展性更强。
内容的提问来源于stack exchange,提问作者Onur Serbes
相关产品推荐
相关产品推荐

