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

@ignsg/react-native-outside

v0.0.5

Published

'Outside' event listener for React Native

Downloads

45

Readme

react-native-outside

A lightweight library for detecting when a user touches outside of a component in React Native. Perfect for implementing modals, dropdowns, and other UI patterns that need to close when clicking outside.

This library has been tested only with Expo on React Native running an iOS development client. Let me know if it doesn't work on your setup.

If this library doesn't work for you, there's another great tool called react-native-outside-press that is also designed to solve the same problem - but in a different way. It may fit your needs better.

Features

  • 🎯 Simple API - Just two components: OutsideRoot and Outside
  • 🪶 Zero layout impact - Components don't render extra views or affect layout
  • 🔄 Nestable - Support for nested outside listeners
  • 🪄 Third party library support - Works with libraries that wrap the native View like re-animated etc.
  • 🛠️ Easy setup - One-line Metro config change

Installation

npm install react-native-outside

Setup

Step 1: Configure Metro

Wrap your Metro config with the withOutside function. This enables the library to intercept View components and detect touch events.

// metro.config.js
const { getDefaultConfig } = require('expo/metro-config');
const { withOutside } = require('react-native-outside/with-outside');

const config = getDefaultConfig(__dirname);

module.exports = withOutside(config);

Note: If you're using a custom Metro resolver, the withOutside function will preserve your existing configuration.

Step 2: Add OutsideRoot

Wrap your app with OutsideRoot. Place it as high in your component tree as possible to ensure all touch events are captured.

import { OutsideRoot } from 'react-native-outside/outside';

function App() {
  return <OutsideRoot>{/* Your app content */}</OutsideRoot>;
}

Usage

Basic Example

import { useState } from 'react';
import { View, Text, Button } from 'react-native';
import { OutsideRoot, Outside } from 'react-native-outside/outside';

function App() {
  const [isModalOpen, setIsModalOpen] = useState(false);

  return (
    <OutsideRoot>
      <View style={{ flex: 1 }}>
        <Button title="Open Modal" onPress={() => setIsModalOpen(true)} />

        {isModalOpen && (
          <Outside onOutsideTouchStart={() => setIsModalOpen(false)}>
            <View>
              <Text>This is a modal. Touch outside to close.</Text>
            </View>
          </Outside>
        )}
      </View>
    </OutsideRoot>
  );
}

Nested Outside Listeners

You can nest Outside components to create complex interactions:

function App() {
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [isDropdownOpen, setIsDropdownOpen] = useState(false);

  return (
    <OutsideRoot>
      <View>
        <Text>Background Content</Text>
      </View>

      {isModalOpen && (
        <Outside onOutsideTouchStart={() => setIsModalOpen(false)}>
          <View>
            <Text>Modal Content</Text>

            {/* Nested dropdown inside modal */}
            <Outside onOutsideTouchStart={() => setIsDropdownOpen(false)}>
              <View>
                <Text>Dropdown</Text>
              </View>
            </Outside>
          </View>
        </Outside>
      )}
    </OutsideRoot>
  );
}

Behavior:

  • Touching the background closes the modal (and dropdown if open)
  • Touching the modal content closes only the dropdown
  • Touching the dropdown closes nothing

API Reference

<OutsideRoot>

The root context provider that manages all outside touch detection.

Props: None

Usage: Place once at the top of your component tree. Does not render any views or affect layout.

<OutsideRoot>{children}</OutsideRoot>

<Outside>

Wraps components that need to detect outside touches.

Props:

| Prop | Type | Required | Description | | --------------------- | ------------------------------ | -------- | -------------------------------------------------------- | | onOutsideTouchStart | (event: NativeEvent) => void | No | Callback fired when a touch starts outside the component | | onOutsideTouchEnd | (event: NativeEvent) => void | No | Callback fired when a touch ends outside the component |

Usage: Wrap any component where you want to detect outside touches. Does not render any views or affect layout.

<Outside
  onOutsideTouchStart={(event) => console.log('Touch started outside')}
  onOutsideTouchEnd={(event) => console.log('Touch ended outside')}>
  {children}
</Outside>

How It Works

Magic 🪄 ... Nah not really, react-native-outside intercepts imports of react-native and replaces the native View component with a lightweight proxy. The proxy:

  1. Intercepts touch events on all View components
  2. Forwards events to the OutsideRoot context
  3. Passes all props and events through to the original View

The OutsideRoot maintains a registry of active Outside listeners. When a touch occurs, it determines which listeners are "outside" the touch target and triggers their callbacks.

Key Points:

  • The proxy has no performance impact on the original View component
  • All touch events are still handled normally by React Native
  • The library only adds minimal event forwarding logic

Common Use Cases

  • Modals - Close when tapping the backdrop
  • Dropdowns - Close when selecting an option or tapping outside
  • Popovers - Dismiss when interacting with other UI
  • Context menus - Close after selection or outside tap
  • Bottom sheets - Dismiss on backdrop tap

Troubleshooting

Outside listeners not firing

Problem: Your onOutsideTouchStart callback isn't being called.

Solutions:

  1. Ensure OutsideRoot is placed above the Outside component in the tree
  2. Verify Metro config is properly wrapped with withOutside
  3. Check that you're importing from the correct paths:
    • react-native-outside/outside for components
    • react-native-outside/with-outside for Metro config

Metro bundler errors

Problem: Metro fails to resolve modules after adding withOutside.

Solutions:

  1. Clear Metro cache: npx react-native start --reset-cache
  2. Ensure the withOutside function is called correctly in metro.config.js
  3. Verify that react-native-outside is properly installed in node_modules

License

MIT