expo+rn,echarts图表有很多库,但我最熟悉的是echarts,可是echarts官网又不支持rn版,折腾很久才用上。

先来看下expo+rn中支持的图表(AI推荐)

1. 功能最强大 (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 的库时,未能正确解析或加载依赖,导致运行时对象不全。

结合你的代码,最可能的原因是:

  1. SkiaChart 组件的 renderer 类型配置错误echarts.init 里的 renderer 参数应该是 'skia' 字符串,但你使用了类型断言 as unknown as RendererType,可能绕过了类型检查,但实际传递的不是库所期望的有效值。

  2. 错误的导入路径:根据 @wuba/react-native-echarts 的官方示例,SkiaChart 和 SkiaRenderer 需要从特定的子路径导入,直接从主包导入可能会破坏其内部对 tslib 的引用。

  3. 底层绘图库版本不兼容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嵌入方式做或者其它方案。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐