Skip to content
Sandny Blog
  • Home
  • Java
  • JavaScript
  • AWS
  • Embedded
  • About
Multiple refs for an array of React Elements JavaScript

How to use IntersectionObserver to detect the position in…

  • July 11, 2021July 29, 2021
  • by Coder Kai

When working with web we often need to animate or reveal html elements by detecting the scroll position. One such example would be to display a container for a state variable and scroll. The IntersectionObserver is a useful interface to achieve such functionality.

01. Using IntersectionObserver

IntersectionObserver has a two main parmeters

let observer = new IntersectionObserver(callback, options);
options = {
  root // element for checking root visibility
  rootMargin // margins around the root for visibility
  threshold // A number of percentage of visibility or an array of points as a percentage. For 100% its 1.0 and for 25% its .25
}

For our example we will use root: null and root-margins: '0px', When root is null it will take the browser viewport as the default root. threshold: 0.5 will be used to load the animation when 50% is loaded.

02. Using useCallback with state variables

We need to show the animation only once when the content is showed. For this I will be using a state variable. The state will be set when callback function is triggerred.

  const [isFocused, setFocused] = useState(false);

  const onObserved = useCallback((entries) => {
    const [entry] = entries;
    !isFocused && setFocused(entry.isIntersecting);
  }, []);

Here we have to enclose the callback with useCallback to ensure the function is initialized once. Unless the removing after effect is over will not be successful as it creates more of the reference.

Here we have taken the first element from the entries array and checked isIntersecting property to set animating variable as true

03. Using useEffect to register observer

If you can remember we had used root: null for the observer. But we need to show the content only when this particular view is loaded. For that we can get the outer container ref to a variable and register the observer to it.

export const AnimatedWrapper = () => {
  const containerRef = useRef(null);
  // ...
  return (
    <div ref={containerRef}>
      <AnimatedView isFocused={isFocused} />
    </div>
  );
}

Now to register the observer we will implement useEffect hook.

 useEffect(() => {
    const observer = new IntersectionObserver(onObserved, {
      root: null,
      rootMargin: '0px',
      threshold: 0.5,
    });
    let current = null;

    if (containerRef?.current) {
      current = containerRef.current;
      observer.observe(current);
    }

    return () => {
      if (current) {
        observer.unobserve(current);
      }
    }
  }, [containerRef, onObserved]);

This hook will be called when the containerRef and onObserved is changed. Also note that the return function will unobserve the observer when effect is over.

Full implementation code as follows. The isFocused field is passed to the animated container to make sure that the animation is loaded when the view is focused.

import React, {useRef, useState, useEffect, useCallback} from 'react';

export const AnimatedWrapper = () => {
  const containerRef = useRef(null);
  const [isFocused, setFocused] = useState(false);

  const onObserved = useCallback((entries) => {
    const [entry] = entries;
    !isFocused && setFocused(entry.isIntersecting);
  }, []);
  
  useEffect(() => {
    const observer = new IntersectionObserver(onObserved, {
      root: null,
      rootMargin: '0px',
      threshold: 0.5,
    });
    let current = null;

    if (containerRef?.current) {
      current = containerRef.current;
      observer.observe(current);
    }

    return () => {
      if (current) {
        observer.unobserve(current);
      }
    }
  }, [containerRef, onObserved]);

  return (
    <div ref={containerRef}>
      <AnimatedView isFocused={isFocused} />
    </div>
  );
};

export default AnimatedWrapper;

You can find the API document here https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API

Minimum supported Gradle version is 7.0. Current version is 6.5
How to convert a string into a stream of lines using String.lines() method in Java 11
Coder Kai
A humble developer
IntersectionObserver react.js scoll

Related articles

Multiple refs for an array of React Elements
Using multiple refs for an…
Immutable and Mutable Values in Javascript
07. Immutable and Mutable Values…
wrapper objects in javascript
06. Wrapper objects in Javascript
globals undefined and null values in javascript
05 Global, null and undefined…
Javascript Booleans and Equality
04. Javascript Guide Booleans and…
How to add Chakra UI Animations
Chakra UI Animations
SSL Websocket using Nginx Proxy
SSL Websocket proxy with Nginx…
Change python version correctly
Python is not setting correct…
optimize React.js load time
How to optimize React.js app…
Multiple refs for an array of React Elements
How to dismiss dropdowns when…
Javascript guide Strings
03. Javascript Guide – Strings
How to fetch data with useEffect
How to fetch data with…
add styles to stripe elements
How to add styles to…
Typescript
How to use Typescript with…
how to optimize react-native map view
How to optimize react-native map…
debounce with react hooks
Avoid multiple clicks using debounce…
Numbers inJavascript
02. Javascript Guide – Numbers
Introduction to Javascript
01. Javascript Guide – Introduction…
Nginx Load Balancer with docker…
Create React App Using npx

Categories

  • android 3
  • Apollo Client 1
  • AWS 8
    • AppSync 5
    • EC2 1
    • EKS 1
    • Route53 1
    • S3 1
  • AWS Amplify 1
  • Chakra UI 1
  • Docker 1
  • Embedded 1
  • EmberJS 1
  • FCM 1
  • Godaddy 1
  • GraphQL 3
  • ios 1
  • Jasper 1
  • Java 10
    • Java 11 1
    • Java 14 1
  • JavaEE 2
  • JavaScript 39
    • Express.js 4
    • Javascript Guide 7
    • Node.js 3
    • react-native 4
    • React.js 17
    • Typescript 1
  • Kubernetes 1
  • machine learning 1
  • Maven 2
  • OCaml 3
  • PostgreSQL 1
  • Python 2
  • react-native 4
  • ReactJS 3
  • sass 1
  • Server 6
  • spark 1
  • Terraform 2
  • Ubuntu 4
  • Uncategorized 1
  • webpack 2

Recent Comments

  • binance register on Chakra UI Animations
  • binance account on SSL Websocket proxy with Nginx for Graphql Subscriptions
  • Binance Pag-signup on How to fetch data with useEffect

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

Archives

  • October 2022 3
  • September 2022 7
  • May 2022 1
  • December 2021 1
  • August 2021 1
  • July 2021 6
  • June 2021 3
  • February 2021 1
  • July 2020 1
  • December 2019 5
  • November 2019 6
  • October 2019 3
  • August 2019 1
  • March 2019 1
  • February 2019 1
  • January 2019 2
  • December 2018 1
  • September 2018 2
  • August 2018 1
  • June 2018 1
  • February 2018 1
  • November 2017 2
  • October 2017 5
  • September 2017 1
  • June 2017 1
  • May 2017 10
Sandny Blog space
Theme by Colorlib Powered by WordPress