useEchart 自定义 hooks

584 阅读1分钟

在项目中使用 echart 图表时,重复操作有以下几个部分可以抽出

  • 获取 dom
  • 初始化 echart
  • 卸载销毁实例

所以编写自定义 hooks 的时候就可以考虑到以上几点

  1. 建一个 ref 供外部绑定,echart 初始化需要用到;
  2. 提供一个方法用于 echart 更新,如果调用方法时没有 echart 实例,则创建实例;
  3. useEffect 模拟组件卸载,此时销毁 echart 实例;

以下是完整代码

创建自定义 hooks

useEchart.ts

import { MutableRefObject, useEffect, useRef } from 'react';
import * as echarts from 'echarts';
import { getLocale } from 'umi';

interface UseEchart {
  (): {
    chartEl: React.RefObject<HTMLDivElement>;
    echart: MutableRefObject<echarts.EChartsType | null>;
    updateChart: (option: any) => void;
  };
}

const useEchart: UseEchart = () => {
  const chartEl = useRef<HTMLDivElement>(null);
  const echart = useRef<echarts.ECharts | null>(null);

  const updateChart = (option: any) => {
    if (!echart.current) initChart();
    echart.current?.clear();
    echart.current?.setOption(option);
  };

  const initChart = () => {
    echart.current = echarts.init(chartEl.current as HTMLDivElement, undefined, {
      locale: getLocale() === 'zh-CN' ? 'ZH' : 'EN',
    });
  };

  useEffect(() => {
    // 销毁 chart 实例
    return () => {
      echart.current?.dispose?.();
      echart.current = null;
    };
  }, []);

  return {
    chartEl,
    echart,
    updateChart,
  };
};

export default useEchart;

组件使用

在组件中,通过 useEffect 在 props.data 发生改变时,调用 useEchart 的 updateChart 方法,传入 option 即可。

Component.tsx

import useEchart from '@/hooks/useEchart';
import { MetricScoreTrend } from '@/pages/SmartHome/data';
import moment from 'moment';
import React from 'react';
import { useEffect } from 'react';
import styles from './index.less';

type LineProps = {
  data: MetricScoreTrend[];
};

const Line: React.FC<LineProps> = ({
  data
}) => {
  const { chartEl, updateChart } = useEchart();

  useEffect(() => {
    // 这里是 ecahrt option
    const option = {
      // xxxx
    };
    
    updateChart(option);
  }, [data]);
  return (
    <div className={styles['line-wrap']}>
      <div className={styles['line-ref']} ref={chartEl} />
    </div>
  );
};

export default React.memo(Line);