EXPO+RN echarts图表库,以及如何使用
本文介绍了在React Native中使用ECharts图表的解决方案。作者对比了多个RN图表库,最终选择了@wuba/react-native-echarts,因其完全兼容Web版ECharts且性能优异。文章详细记录了安装过程中遇到的"__extends is not a function"错误,分析其原因是tslib依赖冲突或组件引用方式不当。解决方案包括:1)在pack
expo+rn,echarts图表有很多库,但我最熟悉的是echarts,可是echarts官网又不支持rn版,折腾很久才用上。
先来看下expo+rn中支持的图表(AI推荐)
1. 功能最强大 (ECharts 完全迁移)
-
推荐库:
@wuba/react-native-echarts -
官网:https://wuba.github.io/react-native-echarts/zh-Hans/docs/getting-started/installation
-
核心优势:语法、配置、文档与 Web 版 Apache ECharts 完全一致;基于 SVG/Skia 原生渲染,性能远超旧版 WebView 方案。
-
适用场景:需要地图、复杂混合图,或团队已熟练使用 ECharts。
2. 高性能纯原生 (Expo 首选)
-
推荐库:
exchartz -
核心优势:专为Expo设计,基于 Skia 绘图 + Reanimated 驱动,动画帧率极高;提供简化的 React 组件式 API。
-
适用场景:追求极致流畅体验,或需要纯 Expo Go 调试的项目。
3. 场景化专用库
-
热力图:选
@symbiot.dev/react-native-heatmap,专精日历/活动图。 -
K线/大数据:选
react-native-charts-wrapper(需 Dev Client),直接调用 Android/iOS 原生绘制。 -
金融图表:选
react-native-ballast-charts,支持复杂的时间轴断点处理。 -
仪表盘:选
@tubinex/react-native-charts,包含环形进度条等多种样式。
这几个都是AI推荐的,但最终我选择了第1个,因为它支持echarts,具体安装请查看官网。但我想分享几点:
1 优先推荐使用官网推荐配置。
官方推荐的肯定是最完美的,但要根据你的expo版本,以及你项目的一些配置,我的是54版本,自己构建的包,但是应用官网的就会一直报错(具体请参考下方的报错),也改了版本,降了ecahrts版本均不行。
提示:请注意查看结合你自己的项目配置,版本等信息去选择配置
以下按照官网封装的一个pie组件,但会一直报错。
import React, { useRef, useEffect } from 'react'
import * as echarts from 'echarts/core'
import { LineChart } from 'echarts/charts'
import { GridComponent } from 'echarts/components'
import { SkiaRenderer, SkiaChart } from '@wuba/react-native-echarts'
import { RendererType } from 'echarts/types/src/util/types.js'
echarts.use([SkiaRenderer, LineChart, GridComponent])
interface PieChartProps {
data?: any
option?: any
}
const PieChart = (props: PieChartProps) => {
const { data, option } = props
const skiaRef = useRef<any>(null)
useEffect(() => {
debugger
const chartsOption = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line'
}
],
...option //扩展
}
let chart: any
if (skiaRef.current) {
chart = echarts.init(skiaRef.current, 'light', {
renderer: 'skia' as unknown as RendererType,
width: 400,
height: 400
})
chart.setOption(chartsOption)
}
return () => chart?.dispose()
}, [data, option])
return <SkiaChart ref={skiaRef} />
}
export default PieChart
报错信息(请注意红色处):
WARN Route "./stock/[symbol]/index.tsx" is missing the required default export. Ensure a React component is exported as default.
ERROR [TypeError: Cannot read property '__extends' of undefined]
Call Stack <global> (node_modules\echarts\node_modules\tslib\modules\index.js) loadModuleImplementation (node_modules\@expo\cli\build\metro-require\require.js) guardedLoadModule (node_modules\@expo\cli\build\metro-require\require.js) metroRequire (node_modules\@expo\cli\build\metro-require\require.js) <global> (node_modules\echarts\lib\core\echarts.js)
AI解释
这个错误通常是由 ECharts 与 tslib 依赖版本的冲突,或是组件引用方式不正确引起的。
在你提供的代码里,我注意到几个可能触发此问题的点,逐一排查应该能解决。
🔍 错误原因分析
这个 __extends is not a function 错误,根源是某些打包工具在处理 ECharts 这类依赖 tslib 的库时,未能正确解析或加载依赖,导致运行时对象不全。
结合你的代码,最可能的原因是:
-
SkiaChart组件的renderer类型配置错误:echarts.init里的renderer参数应该是'skia'字符串,但你使用了类型断言as unknown as RendererType,可能绕过了类型检查,但实际传递的不是库所期望的有效值。 -
错误的导入路径:根据
@wuba/react-native-echarts的官方示例,SkiaChart和SkiaRenderer需要从特定的子路径导入,直接从主包导入可能会破坏其内部对tslib的引用。 -
底层绘图库版本不兼容:
SkiaChart依赖@shopify/react-native-skia,如果它的版本与当前环境不匹配,也可能引发此问题,但通常错误提示会更具体。
最终解决方案:
先安装wuba/react-native-echarts,参考官网
1 在package.json中添加如下配置
...
"resolutions": {
"tslib": "^2.8.1",
"echarts/tslib": "^2.8.1"
},
...
2 package.json中,我的wuba,echarts版本
"@wuba/react-native-echarts": "^3.0.1",
"echarts": "^5.5.1",
配置完成后,重新安装及启动
yarn install
npx expo start -c
3 封装BAR
请注意,所有的引入要变成require()方式,要改变官网引入方式,以下仅是我简单封装的,具体的请参考官网配置项。
const echarts = require('echarts/core') as EChartsModule
import React, { useEffect, useMemo, useRef } from 'react'
import { View, useWindowDimensions } from 'react-native'
import { EChartsProps } from '../option'//公共属性
type EChartsModule = {
init: (...args: any[]) => any
use: (modules: any[]) => void
}
type PieRuntime = {
echarts: EChartsModule
SkiaChart: React.ComponentType<any>
}
let pieRuntimeCache: PieRuntime | null | undefined
function getPieRuntime(): PieRuntime | null {
if (pieRuntimeCache !== undefined) {
return pieRuntimeCache
}
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const echarts = require('echarts/core') as EChartsModule
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { BarChart } = require('echarts/charts') as { BarChart: any }
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { GridComponent } = require('echarts/components') as { GridComponent: any }
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { CandlestickChart } = require('echarts/charts') as { CandlestickChart: any }
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { SkiaRenderer, SkiaChart } = require('@wuba/react-native-echarts') as {
SkiaRenderer: any
SkiaChart: React.ComponentType<any>
}
echarts.use([SkiaRenderer, BarChart, GridComponent, CandlestickChart])
pieRuntimeCache = { echarts, SkiaChart }
} catch (error) {
pieRuntimeCache = null
console.log('PieChart runtime unavailable:', error instanceof Error ? error.message : String(error))
}
return pieRuntimeCache
}
const BarChart = (props: EChartsProps) => {
const { option, height = 400, xAxisData, seriesData } = props
const runtime = useMemo(() => getPieRuntime(), [])
const skiaRef = useRef<any>(null)
const { width: windowW } = useWindowDimensions()
useEffect(() => {
if (!runtime || !skiaRef.current || windowW <= 0) return
const chartsOption = {
xAxis: {
type: 'category',
data: xAxisData
},
yAxis: {
type: 'value'
},
series: [
{
data: seriesData,
type: 'line'
}
],
...option //扩展
}
const chart = runtime.echarts.init(skiaRef.current, 'light', {
renderer: 'skia' as any,
width: windowW,
height: height
})
chart.setOption(chartsOption)
return () => chart?.dispose()
}, [height, option, runtime, windowW, xAxisData, seriesData])
if (!runtime) {
return <View />
}
const SkiaChart = runtime.SkiaChart
return (
<View style={{ width: windowW, overflow: 'hidden' }}>
<SkiaChart ref={skiaRef} style={{ width: windowW, height: height }} />
</View>
)
}
export default BarChart

最后,引入到你的项目中,echarts就能正常使用了,但echarts版本能去到^5.5.1,基本上能解决大部分场景了,如果特殊情况,或者echarts不支持,可暂考虑用H5嵌入方式做或者其它方案。
更多推荐
所有评论(0)