Utilizing Intersection Observer with Custom React Hook in TypeScript
Published: 2024-02-24 19:34:54

## Introduction:
In modern web development, creating responsive and dynamic user interfaces is crucial. One common requirement is to determine whether certain elements are within the viewport, enabling actions such as lazy loading of content or triggering animations. In this article, we'll explore how to achieve this using `TypeScript` and `React`, leveraging the `Intersection Observer API` through a custom React hook.

## Understanding Intersection Observer:
Intersection Observer is a web API that allows developers to observe changes in the intersection between an element and its containing ancestor, or the viewport. This is particularly useful for scenarios where you need to know when an element becomes visible or hidden based on scrolling or other dynamic layout changes.

## Creating a Custom React Hook:
We'll start by defining a custom React hook named `useInViewPort`, which encapsulates the logic for observing the intersection of a target element with the viewport. Here's the implementation:

```ts
import { useState, useEffect } from 'react';

function useInViewPort<T extends HTMLElement>(ref: React.RefObject<T>, options?: IntersectionObserverInit) {
  const [ inViewport, setInViewport ] = useState(false);

  useEffect(() => {
    const observer = new IntersectionObserver(([ entry ]) => {
      setInViewport(entry.isIntersecting);
    }, options);

    const currentRef = ref.current;

    if (currentRef) {
      observer.observe(currentRef);
    }

    return () => {
      if (currentRef) {
        observer.unobserve(currentRef);
      }
    };
  }, [ options, ref ]);

  return inViewport;
}

export default useInViewPort;
```

## Utilizing the Hook in a React Component:
Now, let's see how we can use this hook in a React component. Assume we have a div element that we want to observe:

```tsx
import React, { useRef } from 'react';

import useInViewPort from './useInViewPort';

function MyComponent() {
  const targetRef = useRef<HTMLDivElement>(null);
  const inViewport = useInViewPort(targetRef, { threshold: 0.5 });

  return (
    <div>
      <div style={{ height: '1000px' }}>Scroll down</div>
      <div ref={targetRef} style={{ height: '200px', background: inViewport ? 'green' : 'red' }}>
        {inViewport ? 'In viewport' : 'Not in viewport'}
      </div>
    </div>
  );
}

export default MyComponent;
```

In this example, we create a `ref` to the `div` element we want to observe (`targetRef`). We then use the useInViewport hook passing in this ref. The hook returns a boolean value (inViewport) indicating whether the element is currently in the viewport. We use this value to dynamically change the background color of the div based on its visibility.

## Conclusion:
By creating a custom React hook that utilizes the Intersection Observer API, we've enabled a simple yet powerful way to track elements' visibility within the viewport in `TypeScript-based` React applications. This approach enhances the responsiveness and interactivity of web interfaces, opening doors to a wide range of possibilities such as lazy loading content, triggering animations, and optimizing performance. Experiment with this hook in your projects to unlock new ways of enhancing user experiences.