When the page loads I use componentDidMount() to document.createElement(\"script\");
in the layout index.js
of a ReactJS and G
You can use navigateTo from the gatsby-link
package to roll your own Link
component that executes your custom logic before navigating.
Link.jsx
import React from "react";
import { navigateTo } from "gatsby-link";
const RESOURCE_PATH = "https://www.jscache.com/wejs?wtype=selfserveprop&uniq=789&locationId=10467767&lang=en_NZ&rating=true&nreviews=0&writereviewlink=true&popIdx=true&iswide=true&border=false&display_version=2";
const refetchAndNavigate = (path) => () => {
// refetch
const tripadvisorLeft = document.createElement("script");
tripadvisorLeft.src = RESOURCE_PATH;
tripadvisorLeft.async = true;
document.body.appendChild(tripadvisorLeft);
// finally navigate
navigateTo(path);
}
const Link = ({ to, ...propsToPass }) => (
<div {...propsToPass} onClick={refetchAndNavigate(to)}/>
);
export default Link;
I have not tested this code but idea will work.
Could you use a HOC to accomplish what you want. I just threw this together, it will need to be modified.
Create a component something like,
const withTracking = (WrappedComponent) => {
return class withTracking extends React.Component {
constructor(props) {
super(props);
this.trackit = this.trackIt.bind(this);
}
trackIt() {
{
const tripadvisorLeft = document.createElement("script");
tripadvisorLeft.src = "https://www.jscache.com/wejs?wtype=selfserveprop&uniq=789&locationId=10467767&lang=en_NZ&rating=true&nreviews=0&writereviewlink=true&popIdx=true&iswide=true&border=false&display_version=2";
tripadvisorLeft.async = true;
document.body.appendChild(tripadvisorLeft);
}
}
render() {
return (
<div>
<WrappedComponent {...this.props} trackIt={this.trackIt} />
</div>
);
}
}
};
Then in react router wrap it like,
<Route exact path="/pet-of-the-week" component={withTracking(TEST)}/>
And in the component use componentDidMount,
const TEST = (WrappedComponent) => {
return class ClickLogger extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
this.trackIt();
}
render() {
return (
<div>
<h1>something</h1>
</div>
);
}
}
};
componentDidMount
runs the first time (and only the first time!) the component is mounted in the DOM.
componentDidUpdate
runs every time the component receives new props, but not for the initial render.
In order to operate on the DOM for the first render and for subsequent updates, you'll need to register your <script>
handling logic in both componentDidMount
and componentDidUpdate
, i.e.
class YourComponent extends React.Component {
componentDidMount () {
const tripadvisorLeft = document.createElement("script");
tripadvisorLeft.src = "https://www.jscache.com/wejs?wtype=selfserveprop&uniq=789&locationId=10467767&lang=en_NZ&rating=true&nreviews=0&writereviewlink=true&popIdx=true&iswide=true&border=false&display_version=2";
tripadvisorLeft.async = true;
document.body.appendChild(tripadvisorLeft);
// Keep track of the script tag
this.scriptTag = tripadvisorLeft
}
componentDidUpdate (prevProps) {
// Figure out if the path changed
if (this.props.path !== prevProps.path) {
// Remove the old script tag
document.body.removeChild(this.scriptTag)
// Add it back
const tripadvisorLeft = document.createElement("script");
tripadvisorLeft.src = "https://www.jscache.com/wejs?wtype=selfserveprop&uniq=789&locationId=10467767&lang=en_NZ&rating=true&nreviews=0&writereviewlink=true&popIdx=true&iswide=true&border=false&display_version=2";
tripadvisorLeft.async = true;
document.body.appendChild(tripadvisorLeft);
this.scriptTag = tripadvisorLeft
}
}
}
You can refactor this to move the <script>
creation logic into a helper function, but I've inlined it here to make it clear what's going on.
You can add in the componentDidUpdate
lifecycle method which is called whenever the component is updated:
componentDidUpdate(prevProps) {
// check if path has changed
if (prevProps.pathname !== this.props.pathname) {
// call something to fetch data
}
}
You can add more conditions to match only certain paths.
Check your gastby-link
library to see how you can get the current pathname to pass in as props.
You can also try passing pathname={window.location.pathname}
from a parent component that gets re-rendered when path changes.