Skip to content

React Hooks

@macrulez/inview-react gives the same four capabilities as the Vue composables, built on useSyncExternalStore on top of the same framework-agnostic core engines — same API, same behavior, mirrored 1:1. Import everything from @macrulez/inview-react.

The differences from Vue are structural, not behavioral: plain values instead of Refs (no .value), a plain HTMLElement | null for target instead of MaybeRefOrGetter (React has no ref-as-reactive primitive to accept there — use a state-backed callback ref, not a plain useRef, if target needs to change after mount), and a static snapshot returned on the server via getServerSnapshot. For what each field actually means, see the linked core/Vue pages below — this page only calls out what's React-specific.

Reactive Scroll State

useScroll() — the React equivalent of Reactive Scroll State.

ts
function useScroll(
  target?: Window | HTMLElement | null,
  options?: UseScrollOptions,
): UseScrollReturn

Same fields (x, y, direction, progress, velocity, isScrolling, scrollTo), as plain values instead of refs. options.idleTimeout (default 150) works the same way.

Return value

FieldType
x, ynumber
direction'up' | 'down' | 'left' | 'right' | null
progress, velocitynumber
isScrollingboolean
scrollTo(position: number | { x?: number; y?: number }, options?: ScrollToOptions) => void

Example:

tsx
import { useScroll } from '@macrulez/inview-react'

function ScrollIndicator() {
  const { y, isScrolling } = useScroll()
  return isScrolling ? <p>{y}px</p> : null
}

Element Visibility

useElementVisibility() — the React equivalent of Element Visibility.

ts
function useElementVisibility(
  target: HTMLElement | null,
  options?: UseElementVisibilityOptions,
): UseElementVisibilityReturn

Uses the same shared, pooled visibility engine. optionsthreshold, rootMargin, once, onEnter, onLeave — same shape as Vue, except root: HTMLElement | null (a plain value, not MaybeRefOrGetter).

Real behavioral difference worth knowing: this hook does not read viewportDefaults/setViewportDefaults — those are Vue/Nuxt-only. threshold/rootMargin default to 0/'0px' here purely from the core ObserverPool's own fallback, so calling the Vue package's setViewportDefaults() has no effect on the React adapter.

Return value

FieldType
isVisibleboolean
rationumber

Element Viewport Position

useElementViewport() — the React equivalent of Element Viewport Position.

ts
function useElementViewport(target: HTMLElement | null): UseElementViewportReturn

Returns the same shape — rect, viewportProgress, distanceFromCenter — as plain values.

Parallax Layer

useParallaxLayer() — the React equivalent of Parallax Layer.

ts
function useParallaxLayer(
  target: HTMLElement | null,
  options: UseParallaxLayerOptions,
): UseParallaxLayerReturn

Same options (speed required, axis, clamp, easing, range), same mapping logic, same prefers-reduced-motion behavior. style/progress are memoized with useMemo rather than being a Vue computed.

Return value

FieldType
style{ transform: string }
progressnumber

Example:

tsx
import { useParallaxLayer } from '@macrulez/inview-react'

function ParallaxImage() {
  const ref = useRef<HTMLImageElement | null>(null)
  const { style } = useParallaxLayer(ref.current, { speed: 0.6 })
  return <img ref={ref} style={style} src="/hero.jpg" />
}