0

I'm using highcharts-react-official to render a HighchartsReact component. It shows up and works appropriately until I re-render the component. By changing the state at all, the chart will shrink vertically.

I've experimented with setting reflow in the chart options as well as toggling allowChartUpdate and immutable flags on the component itself to no avail.

const ChartView = props => {
    const { data } = props;
    if(data.highstockData && data.startDate && data.endDate) {
        const min = parseInt(moment(data.startDate, 'x').startOf('day').format('x'));
        const max = parseInt(moment(data.endDate, 'x').startOf('day').format('x'));
        const chartOptions = getChartConfig(data.highstockData,  min, max);

        return (
            <HighchartsReact
                highcharts={Highcharts}
                options={chartOptions}
            />
        )
    }
    return null;
};

And the parent Component's render return:

return (
    <div className="vertical-margin">
        {isFetching && !data && <LoadingView/>}
        {hasError && !data && <ErrorView/>}
        {
            data &&
            <React.Fragment>
                {buttonRow}
                <ChartView
                    data={data}
                />
            </React.Fragment>
        }
    </div>
)

As I said re-rendering for any reason causes the highchart to shrink in height with each re-render. For testing, I call this line:

this.setState({});

I could post the chart config if needed, but it's nothing too fancy.

I haven't been able to find anyone else having this issue and have been pulling my hair out searching for an answer.

Dylan
  • 21
  • 4

1 Answers1

0

It turned out to indeed be a highchart option I was passing into the component. Apparently it was because this option:

scrollbar: {
    enabled: true
},

Was not nested under the xAxis section of the options as it should be. It still created a scrollbar correctly but caused this weird, shrinking issue on component render.

chart: {
            marginRight: 75,
            ignoreHiddenSeries: false,
            panning: false,
            spacingTop: 10,
            height: `${Constants.HIGHCHART_TABLE_HEIGHT}px`,
        },
        time: {
            useUTC: false
        },
        credits: {
            enabled: false
        },
        exporting: {
            enabled: false
        },
        legend: {
            align: 'left',
            enabled: true,
            itemMarginTop: 5,
            itemStyle: {
                "color": "#333333",
                "cursor": "pointer",
                "fontSize": "12px",
                "fontWeight": "normal",
                "width": "240px"
            },
            layout: 'vertical',
            verticalAlign: 'top',
            y: 0
        },
        navigator: {
            enabled: false,
            xAxis: {
                tickPixelInterval: 100
            }
        },
        plotOptions: {
            line: {
                marker: {
                    enabled: true,
                    fillColor: "#ffffff",
                    lineColor: null,
                    lineWidth: 1
                }
            }
        },
        rangeSelector: {
            enabled: false
        },
        tooltip: {
            formatter: function () {
                const sortedPoints = this.points.sort((a, b) => {
                    return a.point.legendOrder - b.point.legendOrder
                });
                return [
                    '<b>',
                    moment(this.x, 'x').format('MM/DD/YYYY HH:mm'),
                    '</b><br/>',
                    sortedPoints.map((item) => {
                        return [
                            '<br/><span style="color:'+ item.series.color +';">\u258c</span> ',
                            '<span>' + item.series.name + '</span>: <b>' + item.y + '</b>',
                            item.comments ? '<p>(' + item.comments + ')</p>' : ''
                        ].join('');
                    }).join('')
                ].join('');
            },
            shared: true,
            crosshairs: {
                color: '#ddd',
                dashStyle: 'solid'
            },
        },
        xAxis: {
            type: 'datetime',
            labels:{
                formatter: function() {
                    const parsed = moment(this.value, 'x');
                    return parsed.format('HH:mm') + '<br/>' + parsed.format('MM/DD');
                }
            },
            min,
            max,
            reversed: true,
            scrollbar: {
                enabled: true
            },
        },
        yAxis: [{
            alignTicks: false,
            max: 60,
            min: 0,
            opposite: false,
            tickInterval: 5,
            title: {
                text: ''
            }
        }, {
            alignTicks: false,
            max: 300,
            min: 0,
            opposite: true,
            tickInterval: 25,
            title: {
                text: ''
            }
        }],

        //The below properties are watched separately for changes.
        series: data,
        title: {
            text: ''
        },
        loading: false,
    };

Also here's the full options file for reference. It wasn't just that scrollbar option causing it. It was a specific combination of options as I discovered by trying to re-create the problem with a new chart.

Dylan
  • 21
  • 4