Reputation: 1230
I've integrated the Google analytics Embed API with my React app and I'm able to render correctly a graph. This is my container, which renders a line chart through the component UsersChart
:
class StatsContainer extends Component {
constructor(props) {
super(props);
initAnalyticsAPI();
}
render() {
return (
<Query query={GET_ACCESS_TOKEN}>
{({ loading: loadingToken, error: errorToken, data: { getAnalyticsAccessToken } }) => (
<Query query={GET_BASIC_STATS}>
{({ loading: loadingStats, error: errorStats, data: { getBasicStats } }) => {
if (loadingToken || loadingStats) return 'Loading...';
if (errorStats) return `Error! ${errorStats.message}`;
else if (errorToken) return `Error! ${errorToken.message}`;
const token = getAnalyticsAccessToken;
return (
<Fragment>
<div className="stats-container">
{/* ... */
<UsersCharts token={token} />
</div>
</Fragment>
);
}}
</Query>
)}
</Query>
);
}
}
initAnalyticsAPI
just appends the script to the document, using the official code:
function loadGA() {
/* eslint-disable */
(function(w,d,s,g,js,fs) {
g = w.gapi || (w.gapi={});
g.analytics = { q:[], ready: function(f) { this.q.push(f); }};
js = d.createElement(s); fs = d.getElementsByTagName(s)[0];
js.src='https://apis.google.com/js/platform.js';
fs.parentNode.insertBefore(js,fs);
js.onload = function() {
g.load('analytics');
};
}(window, document, 'script'));
/* eslint-enable */
}
export default function initialize() {
if (typeof window === 'undefined') {
return false;
}
// avoid downloading the library multiple times if it's already defined
if (_.isEmpty(window.gapi)) {
loadGA();
}
return window.gapi;
}
To keep it short, UsersCharts
renders immediately the container used by the chart, while Google API will load it as soon as it's ready:
class UsersCharts extends Component {
constructor(props) {
super(props);
this.chart = null;
}
componentWillUnmount() {
// how to properly unmount it?
}
render() {
const { token } = this.props;
window.gapi.analytics.ready(() => {
/** Authorize the user with an access token obtained server side. */
window.gapi.analytics.auth.authorize({
serverAuth: {
access_token: token,
},
});
this.chart = new window.gapi.analytics.googleCharts.DataChart({
query: {
...
},
chart: {
...
},
});
this.chart.execute();
});
return (
<Fragment>
<div id="chart-container" />
</Fragment>
);
}
}
The issue is that sometimes I get the following error when I go to another section, which implies that the container for the chart doesn't exist anymore inside the app since another component is rendered. What could I do to properly unmount the component? I search for an API which could allow me to unregister the chart, or at least to catch the error but I wasn't able to find it. Thanks
Upvotes: 2
Views: 1965
Reputation: 1230
Doing a refactoring of UsersChart
by mapping the status of both the library and the component, I was able to get rid of all the warnings:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
class UsersCharts extends Component {
constructor(props) {
super(props);
this._isMounted = false;
this.state = {
ready: false,
};
}
componentDidMount() {
this._isMounted = true;
window.gapi.analytics.ready(() => {
console.log('Ready to do fireworks');
if (this._isMounted) {
this.setState({ ready: true });
}
});
}
componentWillUnmount() {
this._isMounted = false;
}
render() {
const { token } = this.props;
if (this.state.ready) {
/** auth and draw chart */
this.chart.execute();
}
return <div id="chart-container" />;
}
}
Upvotes: 2