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 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-native-global-event

v1.0.15

Published

A powerful React Native global event system for component communication. Solve complex prop drilling, child-to-parent communication, cross-component function calls, and Redux/Saga integration with ease.

Readme

React Native Global Event

🚀 The Ultimate Solution for React Native Component Communication

A powerful and lightweight global event system designed specifically for React Native applications. Solve complex component communication issues, eliminate prop drilling, enable seamless cross-component function calls, and integrate perfectly with Redux/Saga workflows.

🎯 What This Library Solves

React Native developers face unique challenges:

  • Deep Navigation Stacks: Components buried 5+ screens deep need to communicate with root components
  • Redux/Saga Integration: Trigger component functions from Redux actions or Saga effects
  • Cross-Screen Communication: Components on different screens need to interact
  • Navigation Events: Handle navigation events across the entire app
  • State Synchronization: Keep multiple components in sync with global state changes
  • Background/Foreground Events: Handle app state changes across all components
  • Push Notification Handling: Distribute notification events to relevant components
  • Deep Linking: Route deep link events to appropriate components

🚀 Key Features

  • 🎯 React Native Optimized: Built specifically for React Native performance and patterns
  • 🔄 Redux/Saga Integration: Seamlessly trigger component functions from Redux actions
  • 📱 Navigation Support: Perfect for React Navigation and deep navigation stacks
  • ⚡ Performance Optimized: Lightweight with minimal bundle impact
  • 🛡️ TypeScript Support: Full TypeScript support with comprehensive type definitions
  • 🎛️ Dual API: Class-based and Hook-based APIs for different use cases
  • 🔧 Priority System: Execute listeners in priority order
  • 📦 Scoped Events: Organize events with namespaces for better structure
  • 🧹 Automatic Cleanup: Hooks automatically clean up listeners on unmount
  • ⚠️ Error Handling: Graceful error handling with optional warnings

📦 Installation

npm install react-native-global-event
yarn add react-native-global-event

🎯 React Native Use Cases

1. Redux/Saga Integration - Trigger Components from Redux Actions

Problem: You have Redux actions that need to trigger UI updates in specific components, but those components aren't connected to Redux.

// Redux Action
const loginUser = (userData) => ({
  type: 'LOGIN_USER',
  payload: userData
});

// Saga Effect
function* loginUserSaga(action) {
  try {
    const userData = yield call(api.login, action.payload);
    yield put({ type: 'LOGIN_SUCCESS', payload: userData });
    
    // 🚀 Trigger component functions via global event
    globalEvent.emit('redux-user-login', userData);
  } catch (error) {
    globalEvent.emit('redux-login-error', error);
  }
}

// Component that reacts to Redux events
function UserProfile() {
  const [user, setUser] = useState(null);

  useGlobalEventListener('redux-user-login', (userData) => {
    setUser(userData);
    // Show success animation, update UI, etc.
  });

  useGlobalEventListener('redux-login-error', (error) => {
    // Show error message, reset form, etc.
  });

  return user ? <Text>Welcome, {user.name}!</Text> : <Text>Please login</Text>;
}

2. Deep Navigation Communication - Child to Parent Across Screens

Problem: A component deep in your navigation stack needs to communicate with a component on the root screen.

// Deep nested component (5+ screens deep)
function DeepNestedComponent() {
  const { emit } = useGlobalEvent();

  const handleUserAction = (action) => {
    // 🚀 Communicate with root component without prop drilling
    emit('user-action', { action, timestamp: Date.now() });
  };

  return (
    <TouchableOpacity onPress={() => handleUserAction('profile-updated')}>
      <Text>Update Profile</Text>
    </TouchableOpacity>
  );
}

// Root component that listens to deep events
function RootComponent() {
  const [notifications, setNotifications] = useState([]);

  useGlobalEventListener('user-action', (data) => {
    setNotifications(prev => [...prev, data]);
    // Show toast, update badge, etc.
  });

  return (
    <View>
      <Text>Notifications: {notifications.length}</Text>
      {/* Your app content */}
    </View>
  );
}

3. Cross-Screen Communication - Components on Different Screens

Problem: Components on different screens need to communicate with each other.

// Screen A - Product List
function ProductListScreen() {
  const { emit } = useGlobalEvent();

  const addToCart = (product) => {
    // 🚀 Notify cart screen about new item
    emit('product-added-to-cart', product);
  };

  return (
    <FlatList
      data={products}
      renderItem={({ item }) => (
        <TouchableOpacity onPress={() => addToCart(item)}>
          <Text>Add {item.name} to Cart</Text>
        </TouchableOpacity>
      )}
    />
  );
}

// Screen B - Cart Screen
function CartScreen() {
  const [cartItems, setCartItems] = useState([]);

  useGlobalEventListener('product-added-to-cart', (product) => {
    setCartItems(prev => [...prev, product]);
    // Show success animation, update badge, etc.
  });

  return (
    <View>
      <Text>Cart Items: {cartItems.length}</Text>
      {/* Cart content */}
    </View>
  );
}

4. Navigation Events - Handle Navigation Across App

Problem: You need to handle navigation events from anywhere in your app.

// Navigation service
class NavigationService {
  static navigate(screenName, params) {
    // Your navigation logic
    globalEvent.emit('navigation-requested', { screenName, params });
  }
}

// Component that handles navigation
function NavigationHandler() {
  useGlobalEventListener('navigation-requested', ({ screenName, params }) => {
    // Handle navigation logic
    navigation.navigate(screenName, params);
  });

  return null; // This is a service component
}

// Any component can trigger navigation
function AnyComponent() {
  const { emit } = useGlobalEvent();

  const goToProfile = () => {
    emit('navigation-requested', { screenName: 'Profile', params: { userId: 123 } });
  };

  return (
    <TouchableOpacity onPress={goToProfile}>
      <Text>Go to Profile</Text>
    </TouchableOpacity>
  );
}

5. App State Management - Background/Foreground Events

Problem: Handle app state changes across all components.

// App state handler
function AppStateHandler() {
  useEffect(() => {
    const handleAppStateChange = (nextAppState) => {
      globalEvent.emit('app-state-changed', { state: nextAppState });
    };

    const subscription = AppState.addEventListener('change', handleAppStateChange);
    return () => subscription?.remove();
  }, []);

  return null;
}

// Components that react to app state changes
function DataSyncComponent() {
  useGlobalEventListener('app-state-changed', ({ state }) => {
    if (state === 'active') {
      // Sync data when app becomes active
      syncData();
    }
  });

  return <Text>Data Sync Component</Text>;
}

6. Push Notification Handling - Distribute Notifications

Problem: Handle push notifications and distribute them to relevant components.

// Push notification handler
function PushNotificationHandler() {
  useEffect(() => {
    const handleNotification = (notification) => {
      globalEvent.emit('push-notification-received', notification);
    };

    // Your push notification setup
    return () => {
      // Cleanup
    };
  }, []);

  return null;
}

// Components that handle specific notifications
function ChatComponent() {
  useGlobalEventListener('push-notification-received', (notification) => {
    if (notification.type === 'chat') {
      // Handle chat notification
      updateChatList(notification.data);
    }
  });

  return <Text>Chat Component</Text>;
}

7. Deep Linking - Route Deep Link Events

Problem: Handle deep links and route them to appropriate components.

// Deep link handler
function DeepLinkHandler() {
  useEffect(() => {
    const handleDeepLink = (url) => {
      globalEvent.emit('deep-link-received', { url });
    };

    // Your deep link setup
    return () => {
      // Cleanup
    };
  }, []);

  return null;
}

// Components that handle deep links
function ProductDetailComponent() {
  useGlobalEventListener('deep-link-received', ({ url }) => {
    if (url.includes('/product/')) {
      const productId = extractProductId(url);
      // Navigate to product detail
      navigateToProduct(productId);
    }
  });

  return <Text>Product Detail Component</Text>;
}

8. Multiple Components, Same Action - Synchronized Updates

Problem: Multiple components need to perform the same action simultaneously.

// Component A - User Profile
function UserProfile() {
  const [user, setUser] = useState(null);

  useGlobalEventListener('user-data-updated', (userData) => {
    setUser(userData);
    // Update profile UI
  });

  return <Text>Profile: {user?.name}</Text>;
}

// Component B - User Settings
function UserSettings() {
  const [user, setUser] = useState(null);

  useGlobalEventListener('user-data-updated', (userData) => {
    setUser(userData);
    // Update settings UI
  });

  return <Text>Settings for: {user?.name}</Text>;
}

// Component C - User Dashboard
function UserDashboard() {
  const [user, setUser] = useState(null);

  useGlobalEventListener('user-data-updated', (userData) => {
    setUser(userData);
    // Update dashboard UI
  });

  return <Text>Dashboard for: {user?.name}</Text>;
}

// Trigger update from anywhere
function UpdateUserButton() {
  const { emit } = useGlobalEvent();

  const updateUser = () => {
    const newUserData = { name: 'John Doe', email: '[email protected]' };
    // 🚀 All three components will update simultaneously
    emit('user-data-updated', newUserData);
  };

  return (
    <TouchableOpacity onPress={updateUser}>
      <Text>Update User</Text>
    </TouchableOpacity>
  );
}

🚀 Quick Start

Basic Usage

import { globalEvent } from 'react-native-global-event';

// Emit an event
globalEvent.emit('user-login', { userId: 123, username: 'john' });

// Listen to an event
const subscription = globalEvent.on('user-login', (userData) => {
  console.log('User logged in:', userData);
});

// Clean up
subscription.remove();

React Native Hook Usage

import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { useGlobalEvent, useGlobalEventListener } from 'react-native-global-event';

function MyComponent() {
  const { emit } = useGlobalEvent();

  useGlobalEventListener('data-loaded', (data) => {
    console.log('Data received:', data);
  });

  const handlePress = () => {
    emit('button-pressed', { timestamp: Date.now() });
  };

  return (
    <TouchableOpacity onPress={handlePress}>
      <Text>Press Me</Text>
    </TouchableOpacity>
  );
}

📚 API Reference

Class-based API

GlobalEvent

The main class for managing global events.

import { GlobalEvent } from 'react-native-global-event';

const globalEvent = new GlobalEvent();

Methods:

  • emit<T>(eventName: string, data?: T): void - Emit an event
  • on<T>(eventName: string, listener: EventListener<T>, options?: { once?: boolean; priority?: number }): EventSubscription - Register a listener
  • off<T>(eventName: string, listener?: EventListener<T> | string): void - Remove a listener
  • once<T>(eventName: string, listener: EventListener<T>): EventSubscription - Register a one-time listener
  • removeAllListeners(eventName?: string): void - Remove all listeners
  • getListenerCount(eventName: string): number - Get listener count
  • getEventNames(): string[] - Get all event names
  • scope(namespace: string): ScopedGlobalEvent - Create a scoped event manager
  • batchEmit(events: Array<{ name: string; data?: any }>): void - Emit multiple events

ScopedGlobalEvent

Namespace-aware event manager for better organization.

const userEvents = globalEvent.scope('user');
userEvents.emit('login', userData); // Actually emits 'user:login'

Hook-based API

useGlobalEvent

Main hook for event management with automatic cleanup.

const { emit, on, off, once, removeAllListeners, getListenerCount, getEventNames } = useGlobalEvent();

useGlobalEventListener

Hook for listening to a specific event with automatic cleanup.

useGlobalEventListener('user-login', (userData) => {
  console.log('User logged in:', userData);
}, [dependency]);

useGlobalEventOnce

Hook for one-time event listening.

useGlobalEventOnce('initial-data-loaded', (data) => {
  console.log('Initial data loaded:', data);
});

useScopedGlobalEvent

Hook for scoped event management.

const userEvents = useScopedGlobalEvent('user');
userEvents.emit('login', userData);

useGlobalEventState

Hook for managing component state based on events.

const [userData, setUserData] = useGlobalEventState('user-updated', null);
const [isOnline, setIsOnline] = useGlobalEventState(
  'connection-status',
  false,
  (data) => data.status === 'connected'
);

🔧 Configuration

EventManager Options

import { EventManager } from 'react-native-global-event';

const eventManager = EventManager.getInstance({
  maxListeners: 50,        // Maximum listeners per event
  enableWarnings: true     // Enable console warnings
});

Priority System

// Higher priority listeners execute first
globalEvent.on('data-loaded', highPriorityHandler, { priority: 10 });
globalEvent.on('data-loaded', normalHandler, { priority: 5 });
globalEvent.on('data-loaded', lowPriorityHandler, { priority: 1 });

🧪 Testing

The library includes comprehensive unit tests. Run tests with:

npm test
npm run test:coverage

📊 Performance

  • Lightweight: Minimal bundle size impact
  • Efficient: Optimized event handling and cleanup
  • Memory Safe: Automatic cleanup prevents memory leaks
  • Type Safe: Full TypeScript support for better development experience

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • Built specifically for React Native developers
  • Inspired by the need to solve complex component communication in React Native applications
  • Comprehensive testing ensures reliability
  • Made with ❤️ for the React Native community

🚀 Made with ❤️ for React Native developers