title: How do I (correctly) check whether an element is within the viewport in React?
body: <p>In a functional react component, I'm trying to check whether a call to action button (a different component) is within the viewport. If it's not, I want to display a fixed call to action button at the bottom of the viewport, which shows/hides, depending on whether the other button is visible.</p>
  
  <p>I can do this using a combination of Javascript and react hooks, but although the code works in some components in my app, it doesn't work in others; I'm guessing due to react lifecycles. </p>
  
  <p>I'm also aware that this is NOT the way I should be doing things in react, so would prefer to achieve the same result, but in a proper 'react way'. </p>
  
  <p>I've been looking at using refs, but ideally wanted to avoid having to change my functional component to a class, as I'd like to use react hooks for the show/hide of the fixed cta. However, if this is a requirement in order to get the functionality I want, I could go for that.</p>
  
  <p>Here's what I've got so far - basically, I want to replace <code>document.querySelector</code> with a react method:</p>
  
  <pre><code>  useEffect(() =&gt; {
      const CTA = document.querySelector('#CTANextSteps');
      const ApplyStyle = () =&gt; (isInViewport(CTA) ? setVisible(false) : setVisible(true));
      ApplyStyle();
      window.addEventListener('scroll', ApplyStyle);
      window.addEventListener('resize', ApplyStyle);
      return function cleanup() {
        window.removeEventListener('scroll', ApplyStyle);
        window.removeEventListener('resize', ApplyStyle);
      };
    });
  
    const isInViewport = (elem) =&gt; {
      const bounding = elem.getBoundingClientRect();
      return (
        bounding.top &gt;= 0 &amp;&amp;
        bounding.left &gt;= 0 &amp;&amp;
        bounding.bottom &lt;= (window.innerHeight || document.documentElement.clientHeight) &amp;&amp;
        bounding.right &lt;= (window.innerWidth || document.documentElement.clientWidth)
      );
    };
  </code></pre>
  
  <p>As mentioned above, this function works in some areas of the app without issue, but doesn't in others; I get a <code>Cannot read property 'getBoundingClientRect' of null</code> error. I was surprised it worked at all, but rather than tinkering with it to try and get it working everywhere, I want to rewrite it properly.</p>
  
  <p>As always, any assistance would be much appreciated. Thanks.</p>