From 1b69be33d5b24c786e4e028f33389d116752ee0b Mon Sep 17 00:00:00 2001 From: amintai Date: Tue, 10 Sep 2024 15:36:43 +0530 Subject: [PATCH 1/2] Add Intersection Observer API Custome Hook --- src/index.js | 1 + src/useIntersectionObserver.js | 53 ++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/useIntersectionObserver.js diff --git a/src/index.js b/src/index.js index 35f1af5..00ae784 100644 --- a/src/index.js +++ b/src/index.js @@ -32,3 +32,4 @@ export { default as useWhyDidYouUpdate } from './useWhyDidYouUpdate'; export { default as useWindowScroll } from './useWindowScroll'; export { default as useWindowSize } from './useWindowSize'; export { default as useWorker } from './useWorker'; +export { default as useIntersectionObserver } from './useIntersectionObserver'; diff --git a/src/useIntersectionObserver.js b/src/useIntersectionObserver.js new file mode 100644 index 0000000..5117f5d --- /dev/null +++ b/src/useIntersectionObserver.js @@ -0,0 +1,53 @@ +import { useEffect, useRef, useState } from 'react'; + +/** + * useWorker hook + * + * @param {Object} options + * @return {Boolean} isContentVisible - Boolean flag + */ +const useIntersectionObserver = ({ options }) => { + const containerRef = useRef(null); + const [isContentVisible, setContentVisible] = useState(false); + + //! Callback function of IntersectionObserver Function + const callbackFunction = (element) => { + const [entry] = element; + setContentVisible(entry.isIntersecting); + }; + + useEffect(() => { + //! Initialize IntersectionObserver and pass a callback function and options + const observer = new IntersectionObserver(callbackFunction, options); + + if (containerRef.current) observer.observe(containerRef.current); + + return () => { + if (containerRef.current) observer.unobserve(containerRef.current); + }; + }, [containerRef, options]); + + return [{ containerRef, isContentVisible }]; +}; + +export default useIntersectionObserver; + +// usage + +// function App() { +// const options = { +// root: null, +// rootMargin: '0px', +// threshold: 1.0, +// }; +// +// const [{ containerRef, isContentVisible }] = useIntersectionObserver({ options }); + +// return ( +//
+// {isContentVisible ?
Load Only When it's visible in viewport Text
: null} +//
+// ) +// } From 12700e96a9f3c764cde10dae5411c3c128579cb6 Mon Sep 17 00:00:00 2001 From: amintai Date: Tue, 10 Sep 2024 15:56:12 +0530 Subject: [PATCH 2/2] Update Readme file for intersection observer hook --- README.md | 3 ++- docs/useIntersectionObserver.md | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 docs/useIntersectionObserver.md diff --git a/README.md b/README.md index 4876ce1..b02c763 100644 --- a/README.md +++ b/README.md @@ -61,4 +61,5 @@ yarn add react-recipes | 🍷 [`useWhyDidYouUpdate`](./docs/useWhyDidYouUpdate.md) | - | (name, props) | | 🥖 [`useWindowScroll`](./docs/useWindowScroll.md) | { x, y } | - | | 🥮 [`useWindowSize`](./docs/useWindowSize.md) | { height, width } | (initialWidth, initialHeight) | -| 🥝 [`useWorker`](./docs/useWorker.md) | worker instance | (scriptPath, workerOptions, attributes) | +| 🥝 [`useWorker`](./docs/useWorker.md) | worker instance | (scriptPath, workerOptions, attributes) +| 👁 [`useIntersectionObserver`](./docs/useWorker.md) | { ref, isContentVisible } | (options) | diff --git a/docs/useIntersectionObserver.md b/docs/useIntersectionObserver.md new file mode 100644 index 0000000..a27ba74 --- /dev/null +++ b/docs/useIntersectionObserver.md @@ -0,0 +1,38 @@ +# 👁 `useIntersectionObserver` + +A React hook to detect when an element becomes visible in the viewport using the Intersection Observer API. + +## Arguments + +- `options: Object`: Configuration options for the `IntersectionObserver` such as: + - `root: Element`: The element that is used as the viewport for checking visibility of the target (default is `null` for the browser viewport). + - `rootMargin: String`: Margin around the root element (e.g., `'0px'`, `'10px'`). + - `threshold: Number | Array`: A single number or array of numbers which indicate at what percentage of the target's visibility the observer's callback should be executed (e.g., `1.0` means the callback is invoked when 100% of the element is visible) + +## Returns + +- `[{ containerRef, isContentVisible }]` + - `containerRef: RefObject`: Ref to be attached to the DOM element you want to observe. + - `isContentVisible: Boolean`: Boolean flag indicating whether the element is currently visible in the viewport. +## Usage + +```js +import useIntersectionObserver from "react-recipes"; + +function App() { + const options = { + root: null, + rootMargin: '0px', + threshold: 1.0, + }; + + const [{ containerRef, isContentVisible }] = useIntersectionObserver({ options }); + + return ( +
+ {isContentVisible ?
Load Only When it's visible in viewport Text
: null} +
+ ); +} + +``` \ No newline at end of file