Reputation: 633
I have parent component in which I have used the parent highchart component. Something like this
class MobHome extends Component {
render() {
return(
<Link to="/graphdetails">
<AreaSplineChart
id="1keyTotalVisitor"
key="keyTotalVisitor"
className="graph-visitor"
title="<strong>Total Visitors</strong>"
subtitle={`This is all the users that have visited your <br/> site.
<br/><span style='font-size:60px; color: #5BC0BE; font-weight:600'>
${ analyticsData.totalVisitors }</span>`}
data={_.get(analyticsData, 'totalVisitorsGraphData', []).map(t => t.count)}
categories={_.get(analyticsData, 'totalVisitorsGraphData', []).map(t => t._id)}
filterType={this.state.filterType}
graphData={_.get(analyticsData, 'totalVisitorsGraphData', [])}
/>
</Link>
)
}
}
And my highchart(child) component looks Something like this
componentWillReceiveProps (np) {
if (this.props.data !== np.data) {
this.highChartFunction(np)
}
}
class AreaSplineChart extends Component {
highChartFunction () {
const { title, subtitle, id, data, categories, graphData } = this.props
console.log(id)
Highcharts.chart(String(id), {
//... options
})
}
render () {
const { id } = this.props
console.log(id)
return (
<div key={id} id={id}/>
)
}
}
export default AreaSplineChart
Now the issue is working correct in my development mode but gives error in production mode.
Error: Highcharts error #13: www.highcharts.com/errors/13
I have console logs everywhere I am sure my ids
first renders and then my function being called. But still I am getting the issue. Is there any with gatsby production build or I am doing something wrong here?
Thank you!!!
Upvotes: 0
Views: 535
Reputation:
The error given by the Highchart
library means that it could not find the div with the id
you provided. It would seem that componentWillReceiveProps
is called before render.
I would recommend you call your highChartFunction
inside the componentDidMount
lifecycle method and save the Chart
instance to a class property to access it later. componentDidMount
is called right after first call to render
, so the element should be created at this point.
componentDidMount() {
this.highChartFunction();
}
highChartFunction () {
const { title, subtitle, id, data, categories, graphData } = this.props;
this.chart = Highcharts.chart(String(id), {
//... options
});
}
If you want to handle updates to the props I would recommend using componentDidUpdate
, as componentWillReceiveProps
is marked for deprecation and is planned to be removed in React 17. Also there seemed to be some bugs with it. componentDidUpdate
gets the previous props
as an argument so you can check if a update is needed:
componentDidUpdate(prevProps) {
if ("somehow prevProps and this.props is different") { // Replace with check
this.chart.update({
// new options
}, /* Here is an argument to set if the chart should be rerendered, you can set it if necessary */);
}
}
Also don´t forget to set the componentWillUnmount
lifecycle method to destroy the chart:
componentWillUnmount() {
this.chart.destroy();
}
Personal recommendation: I would not use the id
to set the chart, but instead use Refs. Those are references to the component which is in my opinion much better than an id
lookup.
constructor() {
this.chartContainer = React.createRef();
}
highChartFunction() {
/* ... */
Highcharts.chart(this.chartContainer.current, { ... });
}
render() {
const { id } = this.props;
return (<div key={id} id={id} ref={this.chartContainer} />)
}
Here is a minimal example with all I have mentioned here.
Upvotes: 1