or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-react-waypoint

A React component to execute functions when scrolling to specific elements in any scrollable container

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/react-waypoint@10.3.x

To install, run

npx @tessl/cli install tessl/npm-react-waypoint@10.3.0

index.mddocs/

React Waypoint

React Waypoint is a React component that executes callback functions whenever you scroll to an element. It works in all containers that can scroll, including the browser window, and provides callbacks for enter/leave events when elements cross viewport boundaries.

Package Information

  • Package Name: react-waypoint
  • Package Type: npm
  • Language: JavaScript (with TypeScript definitions included)
  • Installation: npm install react-waypoint

Core Imports

import { Waypoint } from 'react-waypoint';

For CommonJS:

const { Waypoint } = require('react-waypoint');

Basic Usage

import React from 'react';
import { Waypoint } from 'react-waypoint';

function App() {
  const handleWaypointEnter = (args) => {
    console.log('Waypoint entered!', args.currentPosition);
  };

  const handleWaypointLeave = (args) => {
    console.log('Waypoint left!', args.currentPosition);
  };

  return (
    <div>
      <div style={{ height: '1000px' }}>Scroll down...</div>
      
      {/* Basic waypoint */}
      <Waypoint
        onEnter={handleWaypointEnter}
        onLeave={handleWaypointLeave}
      />
      
      {/* Waypoint with child element */}
      <Waypoint onEnter={handleWaypointEnter}>
        <div style={{ padding: '20px', background: '#f0f0f0' }}>
          This content triggers waypoint events
        </div>
      </Waypoint>
    </div>
  );
}

Architecture

React Waypoint operates through several key mechanisms:

  • Event-Driven Architecture: Uses scroll and resize event listeners to detect position changes
  • Position Calculation: Calculates element position relative to viewport using getBoundingClientRect()
  • Offset Support: Supports both pixel and percentage-based offsets for flexible triggering
  • Scrollable Ancestor Detection: Automatically finds the closest scrollable container or allows custom specification
  • Lazy Evaluation: Uses onNextTick scheduling to optimize performance and avoid layout thrashing

Capabilities

Waypoint Component

The main React component that provides scroll-based element visibility detection.

class Waypoint extends React.Component<WaypointProps, {}> {
  static above: string;
  static below: string;
  static inside: string;
  static invisible: string;
}

interface WaypointProps {
  /** Function called when waypoint enters viewport */
  onEnter?: (args: CallbackArgs) => void;
  /** Function called when waypoint leaves viewport */
  onLeave?: (args: CallbackArgs) => void;
  /** Function called when waypoint position changes */
  onPositionChange?: (args: CallbackArgs) => void;
  /** Whether to activate on horizontal scrolling instead of vertical */
  horizontal?: boolean;
  /** Distance from top of container in pixels or percentage (e.g., "20px", "20%") */
  topOffset?: string | number;
  /** Distance from bottom of container in pixels or percentage (e.g., "20px", "20%") */
  bottomOffset?: string | number;
  /** Custom ancestor to determine if the target is visible in it */
  scrollableAncestor?: any;
  /** If the onEnter/onLeave events are to be fired on rapid scrolling */
  fireOnRapidScroll?: boolean;
  /** Use this prop to get debug information in the console log */
  debug?: boolean;
  /** Child elements to wrap with waypoint functionality */
  children?: React.ReactNode;
}

interface CallbackArgs {
  /** The position that the waypoint has at the moment */
  currentPosition: string;
  /** The position that the waypoint had before */
  previousPosition: string;
  /** The native scroll event that triggered the callback (may be missing) */
  event?: Event;
  /** The waypoint's distance to the top of the viewport */
  waypointTop: number;
  /** The waypoint's distance to the bottom of the viewport */
  waypointBottom: number;
  /** The distance from the scrollable ancestor to the viewport top */
  viewportTop: number;
  /** The distance from the bottom of the scrollable ancestor to the viewport top */
  viewportBottom: number;
}

Position Constants

Static constants representing different waypoint positions relative to the viewport.

/** Waypoint is above the viewport */
Waypoint.above: string; // "above"
/** Waypoint is below the viewport */
Waypoint.below: string; // "below"
/** Waypoint is inside (visible in) the viewport */
Waypoint.inside: string; // "inside"
/** Waypoint is invisible (e.g., display: none) */
Waypoint.invisible: string; // "invisible"

Callback Events

React Waypoint provides three main callback events for different use cases:

onEnter: Triggered when the waypoint becomes visible in the viewport

<Waypoint
  onEnter={({ currentPosition, previousPosition, event, waypointTop, waypointBottom, viewportTop, viewportBottom }) => {
    console.log('Element entered viewport');
    // Useful for: lazy loading content, analytics tracking, animations
  }}
/>

onLeave: Triggered when the waypoint leaves the viewport

<Waypoint
  onLeave={({ currentPosition, previousPosition, event, waypointTop, waypointBottom, viewportTop, viewportBottom }) => {
    console.log('Element left viewport'); 
    // Useful for: cleanup, pausing videos, stopping animations
  }}
/>

onPositionChange: Triggered whenever the waypoint's position changes

<Waypoint
  onPositionChange={({ currentPosition, previousPosition, event, waypointTop, waypointBottom, viewportTop, viewportBottom }) => {
    console.log(\`Position changed from \${previousPosition} to \${currentPosition}\`);
    // Useful for: scroll spies, position-based UI updates
  }}
/>

Offset Configuration

Control when waypoint events trigger using flexible offset options:

Percentage-based offsets (relative to container height):

<Waypoint
  topOffset="20%"     // Trigger 20% from top of viewport
  bottomOffset="10%"  // Trigger 10% from bottom of viewport
/>

Pixel-based offsets:

<Waypoint
  topOffset={100}        // Trigger 100px from top
  bottomOffset="50px"    // Trigger 50px from bottom
/>

Negative offsets (trigger before entering viewport):

<Waypoint
  topOffset="-100px"     // Trigger 100px before entering viewport
  bottomOffset="-20%"    // Trigger when 20% outside bottom
/>

Horizontal Scrolling

Enable horizontal scroll detection for side-scrolling interfaces:

<Waypoint
  horizontal={true}
  onEnter={() => console.log('Entered horizontal viewport')}
/>

Custom Scrollable Containers

Specify a custom scrollable ancestor instead of auto-detection:

function ScrollableContainer() {
  const containerRef = useRef(null);
  
  return (
    <div ref={containerRef} style={{ height: '300px', overflow: 'auto' }}>
      <div style={{ height: '1000px' }}>
        <Waypoint
          scrollableAncestor={containerRef.current}
          onEnter={() => console.log('Entered custom container viewport')}
        />
      </div>
    </div>
  );
}

Rapid Scroll Handling

Control behavior during rapid scrolling where waypoint might be skipped:

<Waypoint
  fireOnRapidScroll={true}  // Default: fires both onEnter and onLeave during rapid scroll
  fireOnRapidScroll={false} // Skip events during rapid scroll
/>

Debug Mode

Enable detailed console logging for development:

<Waypoint
  debug={true}
  onEnter={() => console.log('Debug information will show in console')}
/>

Child Element Wrapping

Wrap existing elements to track their visibility:

{/* Without children - creates invisible span element */}
<Waypoint onEnter={handleEnter} />

{/* With children - tracks the child element */}
<Waypoint onEnter={handleEnter}>
  <img src="image.jpg" alt="Lazy loaded image" />
</Waypoint>

{/* Multiple children */}
<Waypoint onEnter={handleEnter}>
  <div className="content-section">
    <h2>Section Title</h2>
    <p>Section content...</p>
  </div>
</Waypoint>

Common Use Cases

Lazy Loading Images:

<Waypoint
  onEnter={() => setImageSrc(actualImageUrl)}
  topOffset="-100px" // Start loading before entering viewport
>
  <img src={imageSrc || placeholderSrc} alt="Lazy loaded" />
</Waypoint>

Infinite Scroll:

<Waypoint
  key={currentPage} // Important: use key to recreate waypoint
  onEnter={loadMoreContent}
  bottomOffset="100px" // Trigger before reaching bottom
/>

Scroll Spy Navigation:

<Waypoint
  onPositionChange={({ currentPosition }) => {
    if (currentPosition === 'inside') {
      setActiveSection('section1');
    }
  }}
>
  <section id="section1">Content...</section>
</Waypoint>

Analytics Tracking:

<Waypoint
  onEnter={() => analytics.track('Section Viewed')}
  topOffset="50%" // Trigger when 50% visible
/>