react-native-notifier

repository·main·Indexed 23 days ago

https://github.com/seniv/react-native-notifier

A fast, simple, and customizable in-app notification library for React Native (v3.0.0-rc.5) that supports gestures, various queue modes, and custom components. It provides built-in components like NotifierComponents.Notification and NotifierComponents.Alert, along with a global Notifier API for controlling notifications and broadcasting to multiple instances.

Tokens
9.6K
Snippets
14
Records
48
Agent score
80%

What's inside react-native-notifier

  1. How multiple Notifier instances and broadcasting work

    main

    You can mount multiple NotifierWrapper or NotifierRoot components (for example, inside different modals).

    • Global methods: Notifier.* methods (like showNotification) control the last mounted instance.
    • Broadcasting: Notifier.broadcast.* commands trigger all mounted instances simultaneously.

    This allows you to show notifications inside modals without needing to manage refs manually.

  2. Understand the new duration behavior for hide timers

    main

    In v3.0.0, the duration timer begins after the "appearing" animation finishes, rather than at the start of the animation.

    Impact: If you have a long appearing animation, the notification will stay on screen longer than in previous versions. To maintain previous timing, you may need to lower the duration value.

  3. Implement custom animations using `containerStyle`

    main

    You can create custom animations by passing a function to the containerStyle parameter in showNotification. This function receives an Animated.Value named translateY as its first argument.

    The translateY lifecycle:

    1. -1000: Notification is completely hidden.
    2. -200: Notification is likely still hidden but will be visible soon (depending on component height).
    3. 0: Notification is fully shown.

    Note on Android Shadows: If you animate opacity on components with shadows (like NotifierComponents.Notification), shadows may not animate correctly on Android. To fix this, pass needsOffscreenAlphaCompositing: true via the containerProps parameter.

    Note on iOS Scaling: If scaling animations (e.g., scale) cause the component to move up/down unexpectedly on iOS, it is due to SafeAreaView padding. You can fix this by moving the safe area inset to the container via containerStyle and replacing the ContainerComponent with a standard View.

    const getContainerStyleWithTranslateAndScale = (translateY: Animated.Value) => ({
      transform: [
        {
          // this interpolation is used just to "clamp" the value and didn't allow to drag the notification below "0"
          translateY: translateY.interpolate({
            inputRange: [-1000, 0],
            outputRange: [-1000, 0],
            extrapolate: 'clamp',
          }),
        },
        {
          // scaling from 0 to 0.5 when value is in range of -1000 and -200 because mostly it is still invisible, 
          // and from 0.5 to 1 in last 200 pixels to make the scaling effect more noticeable.
          scale: translateY.interpolate({
            inputRange: [-1000, -200, 0],
            outputRange: [0, 0.5, 1],
            extrapolate: 'clamp',
          }),
        },
      ],
    });
    
    Notifier.showNotification({
      title: 'Custom animations',
      description: 'This notification is moved and scaled',
      containerStyle: getContainerStyleWithTranslateAndScale,
    })
  4. Display notifications above native-stack modals on iOS

    main

    To ensure notifications appear above native-stack modals on iOS, set useRNScreensOverlay to true. This property can be passed as a prop to NotifierRoot/NotifierWrapper or as a parameter to showNotification.

    Known Issue: When useRNScreensOverlay is true, SafeAreaView may not behave correctly. In custom components, use the ViewWithOffsets component to handle safe area insets manually.

  5. Create a custom notification component

    main

    If the built-in components do not meet your needs, you can pass your own React component to the Component property in showNotification.

    Your custom component will automatically receive title, description, and any other values passed inside the componentProps object as props.

    import React from 'react';
    import { StyleSheet, View, Text, SafeAreaView } from 'react-native';
    
    const styles = StyleSheet.create({
      safeArea: {
        backgroundColor: 'orange',
      },
      container: {
        padding: 20,
      },
      title: { color: 'white', fontWeight: 'bold' },
      description: { color: 'white' },
    });
    
    const CustomComponent = ({ title, description }) => (
      <SafeAreaView style={styles.safeArea}>
        <View style={styles.container}>
          <Text style={styles.title}>{title}</Text>
          <Text style={styles.description}>{description}</Text>
        </View>
      </SafeAreaView>
    );
    
    // ...
    
    // Then show notification with the component
    
    Notifier.showNotification({
      title: 'Custom',
      description: 'Example of custom component',
      Component: CustomComponent,
    });
  6. Install and configure react-native-safe-area-context for v3.0.0+

    main

    Starting from v3.0.0, react-native-notifier requires react-native-safe-area-context for internal safe area handling.

    1. Install the dependency:
    yarn add react-native-safe-area-context
    # or
    npm install --save react-native-safe-area-context
    1. Install Pods and rebuild your application.
    2. Wrap your application root (or the NotifierRoot / NotifierWrapper) with <SafeAreaProvider> to ensure correct layout handling.
    import { SafeAreaProvider } from 'react-native-safe-area-context';
    
    const App = () => (
      <SafeAreaProvider>
        <NotifierWrapper>
          {/* ... your app code ... */}
        </NotifierWrapper>
      </SafeAreaProvider>
    );
  7. Setup the NotifierRoot component

    main

    To use the notifier, you must render the NotifierRoot component in your application tree. This component manages the notification lifecycle and provides the interface for the global Notifier API.

    You can pass default parameters via NotifierProps to avoid specifying them in every showNotification call. If you want to prevent the NotifierRoot from being automatically registered with the global Notifier object, set the omitGlobalMethodsHookup prop to true.

  8. Fix iOS scaling/movement issues

    main

    If scaling animations cause the component to move vertically on iOS due to SafeAreaView padding, move the safe area inset to the container and use a standard View as the ContainerComponent.

    Notifier.showNotification({
      title: 'Zoom In/Out Animation',
      containerStyle: (translateY: Animated.Value) => ({
        // add safe area inset to the container
        marginTop: safeTopMargin,
        // ...
      }),
      // replace SafeAreaView with View
      componentProps: {
        ContainerComponent: View,
      },
    })
  9. Fix Android shadow animation issues

    main

    When animating opacity on components with shadows on Android, use the containerProps parameter to pass needsOffscreenAlphaCompositing: true to ensure shadows animate correctly.

    const animatedContainerProps = isAndroid ? { needsOffscreenAlphaCompositing: true } : undefined;
    // ...
    Notifier.showNotification({
      title: 'Custom animations',
      description: 'This notification is moved and scaled',
      containerStyle: getContainerStyleWithTranslateAndScale,
      containerProps: animatedContainerProps,
    })
  10. Implement custom animations using animationFunction

    main

    In v3.0.0, containerStyle only accepts simple style objects. For custom animations, you must use the animationFunction parameter.

    Note: If you previously used custom animations to position a notification at the bottom, consider using the position parameter instead.

    Notifier.showNotification({
      // ...
      animationFunction: ({
        animationState,
        shakingTranslationX,
        shakingTranslationY,
      }: AnimationFunctionParams) => {
        return {
          opacity: animationState,
          transform: [
            {
              translateX: shakingTranslationX,
            },
            {
              translateY: shakingTranslationY,
            },
          ],
        };
      },
    });