Skip to content

Commit ff7c78e

Browse files
committed
drop element argument
1 parent 58c46bc commit ff7c78e

File tree

5 files changed

+37
-33
lines changed

5 files changed

+37
-33
lines changed

src/__tests__/useOnInViewChanged.test.tsx

+10-10
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ const OnInViewChangedComponent = ({
1515
const [callCount, setCallCount] = React.useState(0);
1616
const [cleanupCount, setCleanupCount] = React.useState(0);
1717

18-
const inViewRef = useOnInViewChanged((element, entry) => {
18+
const inViewRef = useOnInViewChanged((entry) => {
1919
setInView(entry ? entry.isIntersecting : false);
2020
setCallCount((prev) => prev + 1);
2121

2222
// Return cleanup function
23-
return (entry) => {
23+
return (cleanupEntry) => {
2424
setCleanupCount((prev) => prev + 1);
25-
if (entry) {
25+
if (cleanupEntry) {
2626
setInView(false);
2727
}
2828
};
@@ -53,7 +53,7 @@ const LazyOnInViewChangedComponent = ({
5353
setIsLoading(false);
5454
}, []);
5555

56-
const inViewRef = useOnInViewChanged((element, entry) => {
56+
const inViewRef = useOnInViewChanged((entry) => {
5757
setInView(entry ? entry.isIntersecting : false);
5858
return () => setInView(false);
5959
}, options);
@@ -232,7 +232,7 @@ const MergeRefsComponent = ({
232232
}: { options?: IntersectionListenerOptions }) => {
233233
const [inView, setInView] = React.useState(false);
234234

235-
const inViewRef = useOnInViewChanged((element, entry) => {
235+
const inViewRef = useOnInViewChanged((entry) => {
236236
setInView(entry ? entry.isIntersecting : false);
237237
return () => setInView(false);
238238
}, options);
@@ -263,17 +263,17 @@ const MultipleCallbacksComponent = ({
263263
const [inView2, setInView2] = React.useState(false);
264264
const [inView3, setInView3] = React.useState(false);
265265

266-
const ref1 = useOnInViewChanged((element, entry) => {
266+
const ref1 = useOnInViewChanged((entry) => {
267267
setInView1(entry ? entry.isIntersecting : false);
268268
return () => setInView1(false);
269269
}, options);
270270

271-
const ref2 = useOnInViewChanged((element, entry) => {
271+
const ref2 = useOnInViewChanged((entry) => {
272272
setInView2(entry ? entry.isIntersecting : false);
273273
return () => setInView2(false);
274274
}, options);
275275

276-
const ref3 = useOnInViewChanged((element, entry) => {
276+
const ref3 = useOnInViewChanged((entry) => {
277277
setInView3(entry ? entry.isIntersecting : false);
278278
return () => setInView3(false);
279279
});
@@ -316,8 +316,8 @@ test("should pass the element to the callback", () => {
316316
let capturedElement: Element | undefined;
317317

318318
const ElementTestComponent = () => {
319-
const inViewRef = useOnInViewChanged((element, entry) => {
320-
capturedElement = element;
319+
const inViewRef = useOnInViewChanged((entry) => {
320+
capturedElement = entry?.target;
321321
return undefined;
322322
});
323323

src/index.tsx

+7-6
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ export { observe } from "./observe";
88

99
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
1010

11-
export type ObserverInstanceCallback = (
11+
export type ObserverInstanceCallback<TElement = Element> = (
1212
inView: boolean,
13-
entry: IntersectionObserverEntry,
13+
entry: IntersectionObserverEntry & { target: TElement },
1414
) => void;
1515

1616
interface RenderProps {
@@ -86,12 +86,13 @@ export type InViewHookResponse = [
8686
};
8787

8888
/**
89-
* The callback called by the useOnInViewChanged hook
89+
* The callback called by the useOnInViewChanged hook once the element is in view
90+
*
91+
* Allows to return a cleanup function that will be called when the element goes out of view or when the observer is destroyed
9092
*/
91-
export type InViewHookChangeListener<TElement extends Element> = (
92-
element: TElement,
93+
export type InViewEnterHookListener<TElement extends Element> = (
9394
/** Entry is always defined except when `initialInView` is true for the first call */
94-
entry: IntersectionObserverEntry | undefined,
95+
entry: (IntersectionObserverEntry & { target: TElement }) | undefined,
9596
) => // biome-ignore lint/suspicious/noConfusingVoidType: Allow no return statement
9697
| void
9798
| undefined

src/observe.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,9 @@ function createObserver(options: IntersectionObserverInit) {
102102
* @param options - Intersection Observer options
103103
* @return Function - Cleanup function that should be triggered to unregister the observer
104104
*/
105-
export function observe(
106-
element: Element,
107-
callback: ObserverInstanceCallback,
105+
export function observe<TElement extends Element>(
106+
element: TElement,
107+
callback: ObserverInstanceCallback<TElement>,
108108
options: IntersectionObserverInit = {},
109109
) {
110110
// An observer with the same options can be reused, so lets use this fact
@@ -114,15 +114,18 @@ export function observe(
114114
let callbacks = elements.get(element);
115115
if (!callbacks) {
116116
callbacks = [];
117-
elements.set(element, callbacks);
117+
elements.set(element, callbacks as ObserverInstanceCallback[]);
118118
observer.observe(element);
119119
}
120120

121-
callbacks.push(callback);
121+
callbacks.push(callback as ObserverInstanceCallback);
122122

123123
return function unobserve() {
124124
// Remove the callback from the callback list
125-
callbacks.splice(callbacks.indexOf(callback), 1);
125+
callbacks.splice(
126+
callbacks.indexOf(callback as ObserverInstanceCallback),
127+
1,
128+
);
126129

127130
if (callbacks.length === 0) {
128131
// No more callback exists for element, so destroy it

src/useInView.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export function useInView(
6161
// Create the ref tracking function using useOnInViewChanged
6262
const refCallback = useOnInViewChanged(
6363
// Combined callback - updates state, calls onChange, and returns cleanup if needed
64-
(_, entry) => {
64+
(entry) => {
6565
setState({ inView: true, entry });
6666

6767
const { onChange } = latestOptions.current;

src/useOnInViewChanged.tsx

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from "react";
22
import type {
3-
InViewHookChangeListener,
3+
InViewEnterHookListener,
44
IntersectionListenerOptions,
55
} from "./index";
66
import { observe } from "./observe";
@@ -20,12 +20,12 @@ import { observe } from "./observe";
2020
* import { useOnInViewChanged } from 'react-intersection-observer';
2121
*
2222
* const Component = () => {
23-
* const inViewRef = useOnInViewChanged((inView, entry, element) => {
24-
* console.log(`Element is ${inView ? 'in view' : 'out of view'}`);
23+
* const inViewRef = useOnInViewChanged((entry) => {
24+
* console.log(`Element is in view`, entry?.target);
2525
* // Optional: cleanup function:
26-
* return () => {
27-
* console.log('Element moved out of view or unmounted');
28-
* };
26+
* return () => {
27+
* console.log('Element moved out of view or unmounted');
28+
* };
2929
* }, {
3030
* threshold: 0,
3131
* });
@@ -39,7 +39,7 @@ import { observe } from "./observe";
3939
* ```
4040
*/
4141
export const useOnInViewChanged = <TElement extends Element>(
42-
onGetsIntoView: InViewHookChangeListener<TElement>,
42+
onGetsIntoView: InViewEnterHookListener<TElement>,
4343
{
4444
threshold,
4545
delay,
@@ -70,13 +70,13 @@ export const useOnInViewChanged = <TElement extends Element>(
7070

7171
let callbackCleanup:
7272
| undefined
73-
| ReturnType<InViewHookChangeListener<TElement>>;
73+
| ReturnType<InViewEnterHookListener<TElement>>;
7474
let didTriggerOnce = false;
7575

7676
// If initialInView is true, we have to call the callback immediately
7777
// to get a cleanup function for the out of view event
7878
if (initialInView) {
79-
callbackCleanup = onGetsIntoViewRef.current(element, undefined);
79+
callbackCleanup = onGetsIntoViewRef.current(undefined);
8080
}
8181

8282
const destroyInviewObserver = observe(
@@ -93,7 +93,7 @@ export const useOnInViewChanged = <TElement extends Element>(
9393
}
9494

9595
// Call callback with inView state, entry, and element
96-
callbackCleanup = onGetsIntoViewRef.current(element, entry);
96+
callbackCleanup = onGetsIntoViewRef.current(entry);
9797

9898
didTriggerOnce = true;
9999

0 commit comments

Comments
 (0)