I have a routable
ArticlePage component that makes an HTTP request to fetch an article. When the request completes, it uses a
<Helmet> tag (
react-helmet) to update the
<title> and several
<meta> tags. The HTTP request is of course asynchronous, and
react-helmet also updates the tags asynchronously, providing a callback to indicate when it's finished.
I want to track the pageview in Google Analytics, and I need the
<title> to be updated because that gets sent to Google Analytics. My question is, how do I ensure that all the asynchronous events have completed before sending the tracking request?
I'm looking for a solution I can use throughout my site with varying levels of page complexity. For example, for some pages, the HTTP request will be made at the
*Page component level, but the
<Helmet> tag may be nested several levels down inside another component, and a third component may be making a separate HTTP request.
Right now I use Redux to keep track of all the async items currently in progress with a simple counter. Each item sends a
readyToTrackPageview(false) action when it starts, and
readyToTrackPageview(true) when it ends. The reducer increments and decrements a counter (respectively) in response to these actions; every time the counter reaches 0, it fires the tracking event.
The problem is, a component that wraps
<Helmet> on the page gets unmounted and remounted in response to some state changes, which means it'll actually fire tracking events twice for a single page. Furthermore, if one async event starts AND finishes before a second one even begins, again, two tracking events would be fired.
I'd like to somehow tie the events to a single router history entry. But if I fire the event as soon as the router updates, the async actions won't have completed yet, and it will track outdated metadata.
Any ideas? Thanks!