haloremi
haloremi

Reputation: 41

Apexcharts - ReactJs - real time - Cannot read property 'filter' of undefined

I have a chart created in a composant (hooks) :

return (
<div id="chart-candlestick">
    <ReactApexChart options={optionsCandles} series={seriesCandles} type="candlestick"
                    height={290}/>
</div>)

and I tried to add values to test the realtime possibility. (Without it, it works fine !) My problem is that I tried for several hours and didn't find why I have this exception.

So, I have named my chart ("candle") in the options :

{
    chart: {
        type: 'candlestick',
        height: 290,
        id: 'candles'   
        {...}
    },
    {...}
}

and so, time to time I tried to used the exec method of ApexCharts to add more data manualy:

function fetchLastDatas() { 
    const date = dateAdd(candleDatas[candleDatas.length - 1].x,"minute",5)
    var obj = {
        x: date,
        y: candleDatas[candleDatas.length - 1].y
    }
    candleDatas.push(obj);

    ApexCharts.exec('candles', 'updateSeries', [{
        data:candleDatas
    }], true)

}

My array has datas but I have this exception on the line "ApexCharts.exec" and I don't know why :

Uncaught TypeError: Cannot read property 'filter' of undefined
    at Function.value (apexcharts.common.js:14)
    at Function.value (apexcharts.common.js:14)
    at fetchLastDatas (ChartCaneva.js:178)
    

I'm new to use this library (and in React in general) so thanks for the help !

Good night (or morning) !

Upvotes: 3

Views: 8328

Answers (5)

DistantSound
DistantSound

Reputation: 1

import React, { useEffect } from "react";
import ApexCharts from 'apexcharts';
import ReactApexChart from "react-apexcharts";
//import { useHookAxios } from "../../ds-hooks/use-hook-axios";
import { colorGroup } from "../hook/hook-apexchart";
import "../css/style.css";

let lastDate = 0;
const data = [];
const TICKINTERVAL = 86400000;
const XAXISRANGE = 777600000;

const generateDayWiseTimeSeries = (baseval, count, yrange) => {
    let i = 0;
    while (i < count) {
        let x = baseval;
        let y = Math.floor(Math.random() * (yrange.max - yrange.min + 1)) + yrange.min;

        data.push({
            x, y
        });
        lastDate = baseval
        baseval += TICKINTERVAL;
        i++;
    }
};

export const DsApexChartLineRealtime = () => {
      generateDayWiseTimeSeries(new Date('11 Feb 2017 GMT').getTime(), 10, {
        min: 10,
        max: 90
    });

    const getNewSeries = (baseval, yrange) => {
        let newDate = baseval + TICKINTERVAL;
        lastDate = newDate;

        for (let i = 0; i < data.length - 10; i++) {
            data[i].x = newDate - XAXISRANGE - TICKINTERVAL
            data[i].y = 0
        };

        data.push({
            x: newDate,
            y: Math.floor(Math.random() * (yrange.max - yrange.min + 1)) + yrange.min
        })
    };


    const series = [
        { data: data.slice() }
    ];
    const options = {
        chart: {
            id: 'realtime',
            type: 'line',
            animations: {
                enabled: true,
                easing: 'linear', //linear easein easeout easeinout
                dynamicAnimation: {
                    speed: 1000
                }
            },
            toolbar: {
                show: false
            },
            zoom: {
                enabled: false
            }
        },
        color: colorGroup,
        title: {
            text: 'Dynamic Updating Chart',
            align: 'center', //left  center right
            offsetY: 5,
            style: {
                fontSize: '30px',
                fontWeight: '600',
                fontFamily: 'Helvetica, Arial, sans-serif',
                color: '#fff'
            }
        },
        grid: {
            show: true,
            borderColor: "#222"
        },
        dataLabels: {
            enabled: false
        },
        stroke: {
            curve: 'smooth'
        },
        markers: {
            size: 0
        },
        xaxis: {
            type: 'datetime',
            range: XAXISRANGE
        },
        yaxis: {
            max: 100
        },
        legend: {
            show: false
        }
    };

 

    useEffect(() => {
        window.setInterval(() => {
            getNewSeries(lastDate, {
                min: 10,
                max: 90
            });
            ApexCharts.exec('realtime', 'updateSeries',
                [{ data: data }]
            )
        }, 1000);

    }, [])

    return (
        <section className="section-group">
            <h5 className="float-l group-h5"> DsApexChartLineRealtime - useHookAxios </h5>
            <div className="container">
                <div className="row">
                    <div className="col-10 push-1">
                        <ReactApexChart options={options} series={series} type="line" height={400} />
                    </div>
                </div>
            </div>
        </section>
    )
};

Upvotes: 0

realsarm
realsarm

Reputation: 657

I have had this issue to fix it I imported both import ReactApexChart from 'react-apexcharts' and import ApexCharts from 'apexcharts' exactly as the doc

Then my char was brush-chart so I called ApexCharts.exec for both parts like the following

   ApexCharts.exec(`linechart`, 'updateSeries', [{data: this.state.graphData, }])

   ApexCharts.exec(`area-chart`, 'updateSeries', [{ data: this.state.graphData, }])

Upvotes: 0

haloremi
haloremi

Reputation: 41

I have needed to change my resolve answers.

In React and Apex-chart, the chart will refresh the options only if you set another reference of your object. In my case I tried with the spread operator and Object.assign.

The problem was that the options of the chart are a complex object. So you need to do a deep copy with a library or a custom function (for performance, I had read "rfdc" is the best)

Upvotes: 0

haloremi
haloremi

Reputation: 41

Sorry, I had a lot of other problem so I didn't response this one. In React you normally don't need to use exec. The modification of the Hooks will perform the change automatically.

Upvotes: 0

wmik
wmik

Reputation: 784

Ran into a similar error a while back.

Seems that ApexCharts.exec is complaining because it's trying to update a component (chart with id='candles') that hasn't been mounted yet.

You could try adding a console.log(document.getElementById('chart-candlestick')) in the update function to check this.

Maybe try adding a condition that checks whether the component is mounted before trying to run any updates.

useRef?


function fetchLastDatas(chartIsMounted) {
  // ...
  // debug: console.log(document.getElementById('chart-candlesticks'));
  if(chartIsMounted !== null) {
    ApexCharts.exec('candles', 'updateSeries', [{ /* ... */}])
  }
}

function Parent() {
  let chartRef = React.useRef(null);

  React.useEffect(() => {
    fetchLastDatas(chartRef.current);
  }, []);

  return <Child chartRef={chartRef} /> // You could use React.forwardRef instead and pass a `ref` prop
}

function Child({ chartRef }) {
  return <ChartContainer chartRef={chartRef} />;
}

function ChartContainer({ chartRef }) {
  return (
    <div id="chart-candlestick">
      <ReactApexChart id='candles' ref={chartRef} />
    </div>
  );
}

Upvotes: 3

Related Questions