0

CODE

export default function EChart({ option, config, resize }) {

    let chart = useRef(null)
    let [chartEl, setChartEl] = useState(chart)



    useEffect(() => {
        if (resize) {
            chartEl.resize()
        }
        if (!chartEl.current) {
            chartEl.setOption(option)
        }
        else {
            // console.log(resizeChart)
            setChartEl(echarts.init(chart.current))
        }
    }, [option, chartEl, resize])

    return (
        <div className="chart" ref={chart}></div>
    )
}

How to fix the setoptions doesn't exist on type MutableRefObject. What I'm trying to do is to display the line chart canvas. but there's a error which is setoptions doesn't exist on type mutablerefobject also the Property 'resize' does not exist on type 'MutableRefObject

  • On first render, `chartEl.current` is `null` – GalAbra Jan 28 '21 at 09:25
  • @GalAbra do I need to remove the null? –  Jan 28 '21 at 09:29
  • 1
    Honestly I'm not sure what are you trying to do in your code and couldn't find documentation for `MutableRefObject`, so I'm not sure how to assist – GalAbra Jan 28 '21 at 09:35
  • 2
    It is only null on the first render, so you can just add a check like `if(chartEl && chartEl.current) { }` in your `useEffect` hook. – Gh05d Jan 28 '21 at 11:25

1 Answers1

1

chartEl is the ref object, not the element. So you would need to access chartEl.current.

But you don't want to be storing the ref to your div as chartEl anyways. A div does not have properties like resize() and setOption(). Those only make sense once you have a chart instance.

The flow of actions here is honestly really tricky as you can't really use refs as a useEffect dependency.

I actually think that this is a good use case for callback refs, where you define the ref as a function of the element.

But then I am using useRef instead of useState to store the chart object itself because state should be immutable and the chart object is mutable.

import React, { useRef, useEffect } from "react";
import { init, ECharts } from "echarts";

interface EChartProps {
  // what are these types really?
  option: any;
  config?: any;
  resize?: any;
}

function EChart({ option, config, resize }: EChartProps) {
  // using a ref instead of state to store the chart because it is mutable
  const chart = useRef<ECharts>();

  // use a callback ref to initialize the chart
  const containerRef = (element: HTMLDivElement | null) => {
    // ignore if already set
    if (element && !chart.current) {
      // create a chart and set properties
      const newChart = init(element);
      newChart.setOption(option);
      newChart.resize();
      // store to the chart ref
      chart.current = newChart;
    }
  };

  useEffect(() => {
    // refresh if option changes
    chart.current?.setOption(option);
  }, [option]);

  return (
    <div
      className="chart"
      // needs some minimum height or else it is 0
      style={{ height: "100vw" }}
      ref={containerRef}
    ></div>
  );
}

export default () => {
  return (
    <EChart
      // example data from https://echarts.apache.org/examples/en/editor.html?c=line-simple
      option={{
        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"
          }
        ]
      }}
    />
  );
};

Code Sandbox Link

Linda Paiste
  • 38,446
  • 6
  • 64
  • 102
  • 1
    This is awesome. It is not the solution I was 'hoping' for, but after researching most of the day yesterday it s the 'only' viable/working solution I have found. Getting Echarts to work w/ React and Next.js easy, actually communicating w/ the instance, a train wreck. – Jeff Bluemel Feb 08 '23 at 17:55