首页 > 解决方案 > How do I (correctly) check whether an element is within the viewport in React?

问题描述

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.

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.

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

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.

Here's what I've got so far - basically, I want to replace document.querySelector with a react method:

  useEffect(() => {
    const CTA = document.querySelector('#CTANextSteps');
    const ApplyStyle = () => (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) => {
    const bounding = elem.getBoundingClientRect();
    return (
      bounding.top >= 0 &&
      bounding.left >= 0 &&
      bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
      bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
    );
  };

As mentioned above, this function works in some areas of the app without issue, but doesn't in others; I get a Cannot read property 'getBoundingClientRect' of null 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.

As always, any assistance would be much appreciated. Thanks.

标签: javascriptreactjsviewport

解决方案


推荐阅读