JavaScript, Programming

Fix React Adsense Already Gave Ads In Them Bug

fix-react-adsense-already-gave-ads-in-them-bug

You may have a react component like that:

import React from 'react';
import PropTypes from 'prop-types';

const initAd = () => {
  (window.adsbygoogle = window.adsbygoogle || []).push({});
};

class Adsense extends React.PureComponent {
  componentDidMount() {
    initAd();
  }

  componentDidUpdate() {
    initAd();
  }

  render() {
    const { children, className, path } = this.props;
    return (
      <div key={path} className={`adsense ${className}`}>
        <ins
          className="adsbygoogle"
          style={{ display: 'block' }}
          data-ad-client="123456"
          data-ad-slot="123456"
          data-ad-format="auto"
          data-full-width-responsive="true"
        />
      </div>
    );
  }
}

Adsense.propTypes = {
  path: PropTypes.string.isRequired,
  className: PropTypes.string,
};

Adsense.defaultProps = {
  className: '',
};

export default Adsense;

The path for refreshing the ad when browser history has been changed, but when you have multiple ads on one page. It will be caused the error and print it in the console like that:

adsbygoogle.push() error: All ins elements in the DOM with class=adsbygoogle already have ads in them.

This is because of multiple Adsense components call initAd() when it updated or rendered. Luckily, React provide shouldComponentUpdate API for us. So we are going to change back the component to extends React.Component and override shouldComponentUpdate method. Only re-render the component when the path has been updated.

import React from 'react';
import PropTypes from 'prop-types';

const initAd = () => {
  (window.adsbygoogle = window.adsbygoogle || []).push({});
};

class Adsense extends React.Component {
  componentDidMount() {
    initAd();
  }

  shouldComponentUpdate(nextProps) {
    const { props: { path } } = this;
    return nextProps.path !== path;
  }

  componentDidUpdate() {
    initAd();
  }

  render() {
    const { children, className, path } = this.props;
    return (
      <div key={path} className={`adsense ${className}`}>
        <ins
          className="adsbygoogle"
          style={{ display: 'block' }}
          data-ad-client="123456"
          data-ad-slot="123456"
          data-ad-format="auto"
          data-full-width-responsive="true"
        />
      </div>
    );
  }
}

Adsense.propTypes = {
  path: PropTypes.string.isRequired,
  className: PropTypes.string,
};

Adsense.defaultProps = {
  className: '',
};

export default Adsense;

Now, no more accidentally update to cause the error again.

Tags: