Remount componentDidMount() by path.name

☆樱花仙子☆ 提交于 2019-12-02 10:34:18

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 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.

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.

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>
            );
        }
    }
};
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!