apexcharts / react-apexcharts

📊 React Component for ApexCharts
https://apexcharts.com
MIT License
1.3k stars 152 forks source link

Problem when updating options (Next.js) #549

Closed b3ernardo closed 2 months ago

b3ernardo commented 1 year ago

I am using three useState hooks to manage the state of my options. This is necessary because the min and max parameters of xaxis can change dynamically based on the startDate and endDate values retrieved from a ContextAPI.

However, I encounter an issue where the chart crashes every time I attempt to set new options to update these parameters. It seems to occur consistently whenever the options' state changes. Is there a recommended approach for updating the options while working with Next.js?

image

Code above:

'use client';
import { LineDataCuba101, GanttDataCuba101, LineDataCuba102, GanttDataCuba102 } from '../utils';
import React, { useEffect, useState } from 'react';
import dynamic from 'next/dynamic';
import Box from '@mui/material/Box';
import { useNavbarContext } from '@/context/NavbarContext';

const Chart = dynamic(() => import('react-apexcharts'), { ssr: false });

export default function Charts() {
    const { cubaSelected, startDate, endDate } = useNavbarContext();
    const [minDate, setMinDate] = useState<number>(startDate.getTime());
    const [maxDate, setMaxDate] = useState<number>(endDate.getTime());

    let LineData, GanttData;
    if (cubaSelected === '102') {
        LineData = LineDataCuba102;
        GanttData = GanttDataCuba102;
    } else {
        LineData = LineDataCuba101;
        GanttData = GanttDataCuba101;
    }

    function formatYAxisLabel(value: number | undefined | null) { (...) };

    const alarmColors: any = { (...) };

    const seriesArray1: any = [ (...) ];

    const seriesArray2: any = [ (...) ];

    const seriesArray3: any = [ (...) ];

    const [optionsLine1, setOptionsLine1] = useState<any>({
        chart: {
            id: 'lineA',
            group: 'sync',
            type: 'line',
            fontFamily: 'Roboto',
            parentHeightOffset: 0,
            animations: {
                enabled: false,
            },
        },
        xaxis: {
            type: 'datetime',
            tickAmount: 20,
            min: minDate,
            max: maxDate,
            labels: {
                show: false,
                datetimeUTC: false,
            },
        },
        (...) 
    });

    const [optionsLine2, setOptionsLine2] = useState<any>({
        chart: {
            id: 'lineB',
            group: 'sync',
            type: 'line',
            toolbar: {
                show: false,
            },
            fontFamily: 'Roboto',
            parentHeightOffset: 0,
        },
        xaxis: {
            type: 'datetime',
            tickAmount: 20,
            min: minDate,
            max: maxDate,
            labels: {
                show: false,
                datetimeUTC: false,
            },
        },
        (...)
    });

    const [optionsTimeline, setOptionsTimeline] = useState<any>({
        chart: {
            id: 'timelineA',
            group: 'sync',
            type: 'rangeBar',
            fontFamily: 'Roboto',
            parentHeightOffset: 0,
        },
        plotOptions: {
            bar: {
                horizontal: true,
                barHeight: '40%',
            },
        },
        xaxis: {
            type: 'datetime',
            min: minDate,
            max: maxDate,
            tickAmount: 20,
            labels: {
                show: true,
                datetimeUTC: false,
            },
        },
        (...)
    });

    useEffect(() => {
        setMinDate(startDate.getTime());
        setMaxDate(endDate.getTime());
    }, [endDate, startDate]);

    useEffect(() => {
        setOptionsLine1({
            ...optionsLine1,
            xaxis: {
                ...optionsLine1.xaxis,
                min: minDate,
                max: maxDate,
            },
        });

        setOptionsLine2({
            ...optionsLine2,
            xaxis: {
                ...optionsLine2.xaxis,
                min: minDate,
                max: maxDate,
            },
        });

        setOptionsTimeline({
            ...optionsTimeline,
            xaxis: {
                ...optionsTimeline.xaxis,
                min: minDate,
                max: maxDate,
            },
        });
    }, [minDate, maxDate]);

    return (
        <Box
            display='flex'
            flexDirection='row'
            alignItems='center'
            justifyContent='center'
            padding='8px'
            bgcolor='#FFFFFF'
            boxShadow={2}
            width='100%'
        >
            <div className='sync' style={{ width: '98%', height: '100%' }}>
                <div className='lineA' style={{ margin: '0px 0px -20px 0px', width: 'calc(100% - 5px)', height: '35%' }}>
                    <Chart
                        options={optionsLine1}
                        series={seriesArray1}
                        type='line'
                        height='100%'
                        width='100%'
                    />
                </div>
                <div className='lineB' style={{ margin: '0px 0px -20px 0px', width: 'calc(100% - 5px)', height: '35%' }}>
                    <Chart
                        options={optionsLine2}
                        series={seriesArray2}
                        type='line'
                        height='100%'
                        width='100%'
                    />
                </div>
                <div className='timelineA' style={{ margin: '0px 0px -15px 0px', width: '100%', height: '35%' }}>
                    <Chart
                        options={optionsTimeline}
                        series={seriesArray3}
                        type='rangeBar'
                        height='100%'
                        width='100%'
                    />
                </div>
            </div>
        </Box>
    );
};
b3ernardo commented 1 year ago

Edit: I solved it by destroying and recreating the chart. However, this is not an ideal solution, and I'm wondering if there's a better approach.

github-actions[bot] commented 2 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.