Is there a particular way navigation tracking should be done? I couldn't find anything about it in the docs, but looking through the source code I found a solution, but I don't think it's ideal.
What I ended up doing was writing a component NavigationTracker.tsx that uses context.location from the Location component child callback.
import * as React from 'react';
import * as ReactGA from 'react-ga';
interface NavigationTrackerProps {
pathname: string;
children?: React.ReactNode;
}
export default class NavigationTracker extends React.Component<
NavigationTrackerProps
> {
componentDidMount() {
this.pageview(this.props.pathname);
}
componentDidUpdate(prevProps: NavigationTrackerProps) {
if (this.props.pathname !== prevProps.pathname) {
this.pageview(this.props.pathname);
}
}
pageview(pathname: string) {
ReactGA.set({ page: pathname });
ReactGA.send({ hitType: 'pageview' });
}
render(): React.ReactNode {
return this.props.children || null;
}
}
In use it looks like:
<LocationProvider>
<Router>
{...routes}
</Router>
<Location
children={context => (
<NavigationTracker pathname={context.location.pathname} />
)}
/>
</LocationProvider>
If it turns out this has not been accounted for, I'm happy to give it a shot if I get some guidance on how it should be built.
To start it off, I guess what I'd like to see is something like:
<Router onChange={location => {/* do whatever */}}>
{...routes}
</Router>
alternatively just exposing the history.listen function.
EDIT: First version of NavigationTracker.tsx didn't work as expected
history.listen is available outside of the React component tree via createHistory: https://reach.tech/router/api/createHistory
But your NavigationTracker is correct and ideal. I'd got with that.
Yep, I've got something like this in my app:
import Component from '@reactions/component'
const track = pathname => { /* ... */ }
const TrackPageViews = () => (
<Location>
{({ location }) => (
<Component
location={location}
didMount={() => track(location.pathname)}
didUpdate={({ prevProps }) => {
if (prevProps.location !== location) {
track(location.pathname)
}
}}
/>
)}
</Location>
)
Excellent, thanks :)
Usage:
const App = () => (
<div>
<TrackPageViews/>
<Router>
{/* ... */}
</Router>
</div>
)
Most helpful comment
Yep, I've got something like this in my app: