You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

react-intersection-observer-hook

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-intersection-observer-hook - npm Package Compare versions

Comparing version

to
4.0.0

11

dist/index.d.ts

@@ -5,5 +5,5 @@ type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

type IntersectionObserverHookRefCallbackNode = Element | null;
type IntersectionObserverHookRefCallback = (node: IntersectionObserverHookRefCallbackNode) => void;
type IntersectionObserverHookRefCallback = (node: IntersectionObserverHookRefCallbackNode) => VoidFunction;
type IntersectionObserverHookRootRefCallbackNode = IntersectionObserverInit['root'];
type IntersectionObserverHookRootRefCallback = (node: IntersectionObserverHookRootRefCallbackNode) => void;
type IntersectionObserverHookRootRefCallback = (node: IntersectionObserverHookRootRefCallbackNode) => VoidFunction;
type IntersectionObserverHookResult = [

@@ -18,3 +18,5 @@ IntersectionObserverHookRefCallback,

type TrackVisibilityHookArgs = IntersectionObserverHookArgs;
type TrackVisibilityHookArgs = IntersectionObserverHookArgs & {
once?: boolean;
};
type TrackVisibilityHookResult = [

@@ -24,7 +26,6 @@ IntersectionObserverHookResult[0],

isVisible: boolean;
wasEverVisible: boolean;
}
];
declare function useTrackVisibility(args?: IntersectionObserverHookArgs): TrackVisibilityHookResult;
declare function useTrackVisibility(args?: TrackVisibilityHookArgs): TrackVisibilityHookResult;
export { type IntersectionObserverHookArgs, type IntersectionObserverHookRefCallback, type IntersectionObserverHookRefCallbackNode, type IntersectionObserverHookResult, type IntersectionObserverHookRootRefCallback, type IntersectionObserverHookRootRefCallbackNode, type TrackVisibilityHookArgs, type TrackVisibilityHookResult, useIntersectionObserver, useTrackVisibility };

@@ -1,1 +0,154 @@

"use strict";var I=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var E=Object.prototype.hasOwnProperty;var m=(r,e)=>{for(var t in e)I(r,t,{get:e[t],enumerable:!0})},h=(r,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of H(e))!E.call(r,o)&&o!==t&&I(r,o,{get:()=>e[o],enumerable:!(s=d(e,o))||s.enumerable});return r};var g=r=>h(I({},"__esModule",{value:!0}),r);var M={};m(M,{useIntersectionObserver:()=>y,useTrackVisibility:()=>R});module.exports=g(M);var i=require("react");function p(){let r=new Map;function e({root:t,rootMargin:s,threshold:o}){let c=r.get(t);c||(c=new Map,r.set(t,c));let k=JSON.stringify({rootMargin:s,threshold:o}),b=c.get(k);if(!b){let n=new Map;b={observer:new IntersectionObserver(u=>{u.forEach(O=>{n.get(O.target)?.(O)})},{root:t,rootMargin:s,threshold:o}),entryCallbacks:n},c.set(k,b)}return{observe:(n,a)=>{b.entryCallbacks.set(n,a),b.observer.observe(n)},unobserve:n=>{b.entryCallbacks.delete(n),b.observer.unobserve(n)}}}return{getObserver:e}}var x="0px",V=[0],A=p();function T(r){let e=r?.rootMargin??x,t=r?.threshold??V,s=(0,i.useRef)(null),o=(0,i.useRef)(null),c=(0,i.useRef)(null),[k,b]=(0,i.useState)(),n=(0,i.useCallback)(()=>{let l=s.current;if(!l){b(void 0);return}let v=A.getObserver({root:o.current,rootMargin:e,threshold:t});v.observe(l,C=>{b(C)}),c.current=v},[e,t]),a=(0,i.useCallback)(()=>{let l=c.current,v=s.current;v&&l?.unobserve(v),c.current=null},[]),u=(0,i.useCallback)(l=>{a(),s.current=l,n()},[n,a]),O=(0,i.useCallback)(l=>{a(),o.current=l,n()},[n,a]);return[u,{entry:k,rootRef:O}]}var y=T;var f=require("react");function N(r){let[e,t]=y(r),s=!!t.entry?.isIntersecting,[o,c]=(0,f.useState)(s);return s&&!o&&c(!0),[e,{...t,isVisible:s,wasEverVisible:o}]}var R=N;0&&(module.exports={useIntersectionObserver,useTrackVisibility});
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
useIntersectionObserver: () => use_intersection_observer_default,
useTrackVisibility: () => use_track_visibility_default
});
module.exports = __toCommonJS(src_exports);
// src/use-intersection-observer.ts
var import_react = require("react");
// src/utils.ts
function createObserverCache() {
const cachesByRoot = /* @__PURE__ */ new Map();
function getObserver({
root,
rootMargin,
threshold
}) {
let cacheByRoot = cachesByRoot.get(root);
if (!cacheByRoot) {
cacheByRoot = /* @__PURE__ */ new Map();
cachesByRoot.set(root, cacheByRoot);
}
const cacheKey = JSON.stringify({ rootMargin, threshold });
let cachedObserver = cacheByRoot.get(cacheKey);
if (!cachedObserver) {
const entryCallbacks = /* @__PURE__ */ new Map();
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
const callback = entryCallbacks.get(entry.target);
callback?.(entry);
});
},
{ root, rootMargin, threshold }
);
cachedObserver = { observer, entryCallbacks };
cacheByRoot.set(cacheKey, cachedObserver);
}
return {
observe: (node, callback) => {
cachedObserver.entryCallbacks.set(node, callback);
cachedObserver.observer.observe(node);
},
unobserve: (node) => {
cachedObserver.entryCallbacks.delete(node);
cachedObserver.observer.unobserve(node);
}
};
}
return { getObserver };
}
// src/use-intersection-observer.ts
var DEFAULT_ROOT_MARGIN = "0px";
var DEFAULT_THRESHOLD = [0];
var observerCache = createObserverCache();
function useIntersectionObserver(args) {
const rootMargin = args?.rootMargin ?? DEFAULT_ROOT_MARGIN;
const threshold = args?.threshold ?? DEFAULT_THRESHOLD;
const nodeRef = (0, import_react.useRef)(null);
const rootRef = (0, import_react.useRef)(null);
const observerRef = (0, import_react.useRef)(null);
const [entry, setEntry] = (0, import_react.useState)();
const reinitializeObserver = (0, import_react.useCallback)(() => {
function cleanupObserver() {
const observer = observerRef.current;
const node = nodeRef.current;
if (node) {
observer?.unobserve(node);
setEntry(void 0);
}
observerRef.current = null;
}
function initializeObserver() {
const node = nodeRef.current;
if (!node) return;
const observer = observerCache.getObserver({
root: rootRef.current,
rootMargin,
threshold
});
observer.observe(node, (observedEntry) => {
setEntry(observedEntry);
});
observerRef.current = observer;
}
cleanupObserver();
initializeObserver();
}, [rootMargin, threshold]);
const refCallback = (0, import_react.useCallback)(
(node) => {
nodeRef.current = node;
reinitializeObserver();
return () => {
nodeRef.current = null;
reinitializeObserver();
};
},
[reinitializeObserver]
);
const rootRefCallback = (0, import_react.useCallback)(
(rootNode) => {
rootRef.current = rootNode;
reinitializeObserver();
return () => {
rootRef.current = null;
reinitializeObserver();
};
},
[reinitializeObserver]
);
return [refCallback, { entry, rootRef: rootRefCallback }];
}
var use_intersection_observer_default = useIntersectionObserver;
// src/use-track-visibility.ts
var import_react2 = require("react");
function useTrackVisibility(args) {
const { once, ...rest } = args ?? {};
const [ref, result] = use_intersection_observer_default(rest);
const isVisible = Boolean(result.entry?.isIntersecting);
const [isVisibleOnce, setIsVisibleOnce] = (0, import_react2.useState)(isVisible);
if (once && isVisible && !isVisibleOnce) {
setIsVisibleOnce(true);
}
return [ref, { ...result, isVisible: once ? isVisibleOnce : isVisible }];
}
var use_track_visibility_default = useTrackVisibility;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
useIntersectionObserver,
useTrackVisibility
});
{
"name": "react-intersection-observer-hook",
"version": "3.0.1",
"version": "4.0.0",
"description": "React hook to use IntersectionObserver declaratively.",

@@ -42,27 +42,27 @@ "keywords": [

"scripts": {
"attw:check": "attw --pack .",
"attw": "attw --pack .",
"build": "tsup",
"dev": "tsup --watch",
"lint:check": "eslint . --max-warnings 0",
"lint": "eslint . --max-warnings 0",
"lint:fix": "eslint . --fix --max-warnings 0",
"prepublishOnly": "npm run build",
"publint:check": "publint",
"types:check": "tsc"
"publint": "publint",
"typecheck": "tsc"
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.15.4",
"@arethetypeswrong/cli": "^0.17.1",
"@repo/eslint-config": "*",
"@repo/lint-staged-config": "*",
"@repo/typescript-config": "*",
"@types/react": "^18.3.3",
"@types/react": "^19.0.1",
"eslint": "^8.57.0",
"publint": "^0.2.10",
"react": "^18.3.1",
"tsup": "^8.2.4",
"typescript": "^5.5.4"
"publint": "^0.2.12",
"react": "^19.0.0",
"tsup": "^8.3.5",
"typescript": "^5.7.2"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
"react": ">=19",
"react-dom": ">=19"
}
}

@@ -13,3 +13,3 @@ # react-intersection-observer-hook

This is a simple to use React hook package for using [Insersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) declaratively. By using this hook, you can easily track if a component is visible or not, create lazy loading images, trigger animations on entering or leaving the viewport, implement infinite loading etc.
This is a easy to use React hook package for using [Insersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) declaratively. By using this hook, you can easily track if a component is visible or not, create lazy loading images, trigger animations on entering or leaving the viewport, implement infinite scroll etc.

@@ -22,2 +22,8 @@ **Live demo is [here](https://onderonur.github.io/react-intersection-observer-hook).**

## Versions
For **React v19**, it is recommended to use versions after `v4`, since it uses [cleanup functions for refs](https://react.dev/blog/2024/12/05/react-19#cleanup-functions-for-refs).
For older versions of React, you can stick with `v3` until you migrate to React 19.
## Installation

@@ -31,3 +37,3 @@

```javascript
```jsx
import React, { useEffect } from 'react';

@@ -44,7 +50,8 @@ import { useIntersectionObserver } from 'react-intersection-observer-hook';

useEffect(() => {
console.log(`The component is ${isVisible ? 'visible' : 'not visible'}.`);
}, [isVisible]);
return <SomeComponentToTrack ref={ref} />;
return (
<div>
<p>Component is {isVisible ? 'visible' : 'not visible'}.</p>
<SomeComponentToTrack ref={ref} />
</div>
);
}

@@ -55,3 +62,3 @@ ```

```javascript
```jsx
import React, { useEffect } from 'react';

@@ -65,13 +72,12 @@ import { useIntersectionObserver } from 'react-intersection-observer-hook';

useEffect(() => {
console.log(`The component is ${isVisible ? 'visible' : 'not visible'}.`);
}, [isVisible]);
return (
<ScrollableContainer
// We use `rootRef` callback to set the root node.
ref={rootRef}
>
<SomeComponentToTrack ref={ref} />
</ScrollableContainer>
<div>
<p>Component is {isVisible ? 'visible' : 'not visible'}.</p>
<ScrollableContainer
// We use `rootRef` callback to set the root node.
ref={rootRef}
>
<SomeComponentToTrack ref={ref} />
</ScrollableContainer>
</div>
);

@@ -81,6 +87,5 @@ }

If you just want to track visibility, you can also use `useTrackVisibility` hook.
It has the same API as `useIntersectionObserver` hook. It just returns additional fields as its second tuple item.
If you just want to track visibility, you can also use `useTrackVisibility` hook. It mostly has the same API as `useIntersectionObserver` hook.
```javascript
```jsx
import React, { useEffect } from 'react';

@@ -97,11 +102,14 @@ import { useTrackVisibility } from 'react-intersection-observer-hook';

// `isVisible`: Becomes `true`/`false` based on the response of `IntersectionObserver`.
// `wasEverVisible`: When the observed node becomes visible once, this flag becomes `true` and stays like that.
const [ref, { entry, rootRef, isVisible, wasEverVisible }] =
useTrackVisibility();
const [ref, { entry, rootRef, isVisible }] = useTrackVisibility({
// In addition to the `IntersectionObserver` arguments, you can use `once` flag
// to watch the visibility of an element once, so `isVisible` stays `true` after the element is visible for the first time.
// once: true,
});
useEffect(() => {
console.log(`The component is ${isVisible ? 'visible' : 'not visible'}.`);
}, [isVisible]);
return <SomeComponentToTrack ref={ref} />;
return (
<div>
<p>Component is {isVisible ? 'visible' : 'not visible'}.</p>
<SomeComponentToTrack ref={ref} />
</div>
);
}

@@ -114,9 +122,15 @@ ```

Both `useIntersectionObserver` and `useTrackVisibility` gets the same arguments. And those are;
### `useIntersectionObserver`
- **rootMargin:** Indicates the margin value around the root element. Default value is zero for all directions (top, right, bottom and left).
- **threshold:** Threshold value (or values) to trigger the observer.
- `rootMargin`: Indicates the margin value around the root element. Default value is `0` for all directions (top, right, bottom and left).
- `threshold`: Threshold value (or values) to trigger the observer.
_For more info, you can check [here](https://developers.google.com/web/updates/2016/04/intersectionobserver) and [here](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)._
### useTrackVisibility
Gets the same arguments as `useIntersectionObserver`. In addition:
- `once`: When set `true`, `isVibisle` stays as `true` after the element is visible for the first time. Default `false`.
## Contributors ✨

@@ -123,0 +137,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet