npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@devx-commerce/react-native-viewport-observer

v1.0.4

Published

feature for having more videos forhandling smoothly in react native without extra load.

Readme

@devx-commerce/react-native-viewport-observer

A React Native library that tracks whether a view is visible on screen. Built for smooth video feed experiences — plays a video when it scrolls into view and pauses it when it scrolls out, without extra load or jank.

Works on both iOS and Android using native viewport observers.

Installation

npm install @devx-commerce/react-native-viewport-observer

or

yarn add @devx-commerce/react-native-viewport-observer

Usage

Wrap any component with VisibilityView. It fires onFocus when the view becomes visible and onBlur when it leaves the screen.

import { VisibilityView } from '@devx-commerce/react-native-viewport-observer';

<VisibilityView
  style={{ flex: 1 }}
  threshold={0.8}
  onFocus={() => console.log('visible')}
  onBlur={() => console.log('hidden')}
>
  {/* your content */}
</VisibilityView>

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | threshold | number | 0.5 | Fraction of the view that must be visible to trigger onFocus. Range: 0.0 – 1.0 | | trackDuringScroll | boolean | false | Emit onFocus/onBlur during an active scroll instead of only after it settles. See During-scroll tracking. | | onFocus | () => void | — | Called when the view enters the viewport | | onBlur | () => void | — | Called when the view exits the viewport | | style | ViewStyle | — | Standard React Native view styles | | ...ViewProps | — | — | All other standard View props are supported |

Example — Auto-play Video Feed

This is the primary use case: a scrollable feed where videos auto-play when visible and pause when scrolled away.

import { useState, useRef } from 'react';
import { View, StyleSheet } from 'react-native';
import Video from 'react-native-video';
import { VisibilityView } from '@devx-commerce/react-native-viewport-observer';
import { FlashList } from '@shopify/flash-list';

const videos = [
  { id: '1', url: 'https://example.com/video1.mp4' },
  { id: '2', url: 'https://example.com/video2.mp4' },
  { id: '3', url: 'https://example.com/video3.mp4' },
];

const VideoRow = ({ url }: { url: string }) => {
  const [paused, setPaused] = useState(true);
  const videoRef = useRef<any>(null);
  const isReady = useRef(false);
  const isFocused = useRef(false);

  return (
    <View style={styles.videoContainer}>
      <VisibilityView
        style={{ flex: 1 }}
        threshold={0.8}
        onFocus={() => {
          isFocused.current = true;
          // Only play once the video is ready to display
          if (isReady.current) setPaused(false);
        }}
        onBlur={() => {
          isFocused.current = false;
          setPaused(true);
        }}
      >
        <Video
          ref={videoRef}
          source={{ uri: url }}
          paused={paused}
          repeat
          resizeMode="cover"
          style={StyleSheet.absoluteFill}
          onReadyForDisplay={() => {
            isReady.current = true;
            // Start playing if already in view
            if (isFocused.current) setPaused(false);
          }}
        />
      </VisibilityView>
    </View>
  );
};

export default function App() {
  return (
    <View style={{ flex: 1 }}>
      <FlashList
        data={videos}
        renderItem={({ item }) => <VideoRow url={item.url} />}
        keyExtractor={(item) => item.id}
        estimatedItemSize={500}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  videoContainer: {
    height: 500,
    backgroundColor: 'black',
    marginVertical: 6,
  },
});

How it works

VisibilityView uses native view tracking on iOS and Android to detect how much of the view is within the visible screen area. When the visible fraction crosses the threshold, it fires onFocus. When it drops below, it fires onBlur.

This is more reliable and performant than JS-based scroll position calculations because:

  • No scroll event listeners needed
  • Works with any scroll container (FlatList, FlashList, ScrollView, etc.)
  • Native-level precision — no frame drops

During-scroll tracking

By default (trackDuringScroll={false}) the observer reports visibility only once a scroll settles — it stays quiet while the list is moving. This keeps scrolling cheap when you have many observed views, and is the right default for most cases.

Set trackDuringScroll={true} to also receive onFocus/onBlur while the list is scrolling. Use it when a view must react the instant it enters or leaves the viewport mid-scroll — e.g. keeping the on-screen video in a feed playing as the user scrolls, while off-screen ones pause.

<VisibilityView
  style={{ flex: 1 }}
  threshold={0.6}
  trackDuringScroll
  onFocus={() => setPaused(false)}
  onBlur={() => setPaused(true)}
>
  {/* video */}
</VisibilityView>

Notes:

  • Opt-in per view. Views that don't set it keep the cheaper settle-only behaviour.
  • Cost. During-scroll tracking runs the visibility check each frame while scrolling — enable it only where the live feedback is worth it, and cap how many such views can be active at once if you have a busy screen.
  • Platform detail. Android re-checks on each throttled scroll frame; iOS emits on each display-link frame while the scroll offset is changing. Both fall back to settle-only when the prop is off.

Tips

  • Use threshold={0.8} for videos so they only play when mostly visible
  • Use threshold={0.1} for lazy-loading content that should trigger early
  • Combine with onReadyForDisplay from react-native-video to avoid playing before the first frame is decoded (prevents black flash)
  • Save video playback position in a Map keyed by URL to resume from the same spot when the video re-enters view

Contributing

License

MIT


Made with create-react-native-library