You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Based on the great work in #718 by @jantimon - This is an attempt to implement just the useOnInView hook, while maintaining the fallback functionality, and legacy React version support.
### ✨ New
- **`useOnInView` hook** — a no-re-render alternative to `useInView` that delivers `(inView, entry)` to your callback while returning a ref you can attach to any element. Designed for tracking, analytics, and other side effect heavy workloads where state updates are unnecessary.
- **`IntersectionChangeEffect` / `IntersectionEffectOptions` types** — exported helper types that describe the new hook’s callback and options surface.
- **Storybook playground + documentation** — new story, README section, and JSDoc example demonstrating how to use `useOnInView`.
### ✨ Improvements
- `useInView`, `useOnInView`, and `<InView>` now ignore the browser’s initial `inView === false` emission so handlers only fire once a real visibility change occurs, while still reporting all subsequent enter/leave transitions (including threshold arrays).
- Observer cleanup logic across the hooks/components was tightened to ensure `skip` toggles and fallback scenarios re-attach correctly without losing previous state.
### 🧪 Testing
- Added a dedicated Vitest suite for `useOnInView`, covering thresholds, `triggerOnce`, `skip` toggling, merged refs, and multiple observers on the same node.
Copy file name to clipboardExpand all lines: README.md
+78-7Lines changed: 78 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,8 +10,8 @@ to tell you when an element enters or leaves the viewport. Contains [Hooks](#use
10
10
11
11
## Features
12
12
13
-
- 🪝 **Hooks or Component API** - With `useInView` it's easier than ever to
14
-
monitor elements
13
+
- 🪝 **Hooks or Component API** - With `useInView`and `useOnInView`it's easier
14
+
than ever to monitor elements
15
15
- ⚡️ **Optimized performance** - Reuses Intersection Observer instances where
16
16
possible
17
17
- ⚙️ **Matches native API** - Intuitive to use
@@ -71,6 +71,72 @@ const Component = () => {
71
71
};
72
72
```
73
73
74
+
> **Note:** The first `false` notification from the underlying IntersectionObserver is ignored so your handlers only run after a real visibility change. Subsequent transitions still report both `true` and `false` states as the element enters and leaves the viewport.
75
+
76
+
### `useOnInView` hook
77
+
78
+
```js
79
+
constinViewRef=useOnInView(
80
+
(inView, entry) => {
81
+
if (inView) {
82
+
// Do something with the element that came into view
83
+
console.log("Element is in view", entry.target);
84
+
} else {
85
+
console.log("Element left view", entry.target);
86
+
}
87
+
},
88
+
options // Optional IntersectionObserver options
89
+
);
90
+
```
91
+
92
+
The `useOnInView` hook provides a more direct alternative to `useInView`. It
93
+
takes a callback function and returns a ref that you can assign to the DOM
94
+
element you want to monitor. Whenever the element enters or leaves the viewport,
95
+
your callback will be triggered with the latest in-view state.
96
+
97
+
Key differences from `useInView`:
98
+
-**No re-renders** - This hook doesn't update any state, making it ideal for
99
+
performance-critical scenarios
100
+
-**Direct element access** - Your callback receives the actual
101
+
IntersectionObserverEntry with the `target` element
102
+
-**Boolean-first callback** - The callback receives the current `inView`
103
+
boolean as the first argument, matching the `onChange` signature from
104
+
`useInView`
105
+
-**Similar options** - Accepts all the same [options](#options) as `useInView`
106
+
except `onChange`, `initialInView`, and `fallbackInView`
107
+
108
+
> **Note:** Just like `useInView`, the initial `false` notification is skipped. Your callback fires the first time the element becomes visible (and on every subsequent enter/leave transition).
> **Note:**`<InView>` mirrors the hook behaviour—it suppresses the very first `false` notification so render props and `onChange` handlers only run after a genuine visibility change.
102
170
103
171
### Plain children
104
172
@@ -145,6 +213,9 @@ Provide these as the options argument in the `useInView` hook or as props on the
145
213
|**initialInView**|`boolean`|`false`| Set the initial value of the `inView` boolean. This can be used if you expect the element to be in the viewport to start with, and you want to trigger something when it leaves. |
146
214
|**fallbackInView**|`boolean`|`undefined`| If the `IntersectionObserver` API isn't available in the client, the default behavior is to throw an Error. You can set a specific fallback behavior, and the `inView` value will be set to this instead of failing. To set a global default, you can set it with the `defaultFallbackInView()`|
147
215
216
+
`useOnInView` accepts the same options as `useInView` except `onChange`,
217
+
`initialInView`, and `fallbackInView`.
218
+
148
219
### InView Props
149
220
150
221
The **`<InView />`** component also accepts the following props:
0 commit comments