React Native SDK

Complete guide to using PushBase React Native SDK

React Native SDK

The PushBase React Native SDK is a comprehensive wrapper around React Native Firebase messaging that simplifies push notification implementation with automatic token management, permission handling, and message processing.

Installation

Prerequisites

Ensure you have React Native Firebase properly configured:

Install PushBase SDK

<package_manager> [install|add] @pushbase/react-native

iOS Setup

For iOS, you need to configure APNs. Follow the React Native Firebase iOS setup guide.

Android Setup

For Android, ensure you have the google-services.json file in your project. Follow the React Native Firebase Android setup guide.

Quick Start

import { PushBase } from "@pushbase/react-native";

// Initialize the SDK
const pushBase = PushBase.getInstance({
  debug: true,
  autoInitialize: true,
  androidChannelId: "my_app_notifications",
  androidChannelName: "My App Notifications",
});

// Initialize and request permissions
const initializePushNotifications = async () => {
  try {
    await pushBase.initialize();
    const permissions = await pushBase.requestPermissions();

    if (permissions.granted) {
      const token = await pushBase.getToken();
      console.log("FCM Token:", token);
    }
  } catch (error) {
    console.error("Push notification setup failed:", error);
  }
};

// Set up message listeners
pushBase.onMessage((message) => {
  console.log("Foreground message:", message);
});

pushBase.onBackgroundMessage((message) => {
  console.log("Background message:", message);
});

pushBase.onTokenRefresh((token) => {
  console.log("Token refreshed:", token);
});

Configuration

PushBaseConfig

interface PushBaseConfig {
  /** Enable debug logging */
  debug?: boolean;
  /** Custom notification channel for Android */
  androidChannelId?: string;
  /** Custom notification channel name for Android */
  androidChannelName?: string;
  /** Auto-initialize the SDK */
  autoInitialize?: boolean;
  /** Custom server endpoint for token registration */
  serverEndpoint?: string;
  /** Additional metadata to send with token */
  metadata?: Record<string, any>;
}

Example Configuration

const config: PushBaseConfig = {
  debug: __DEV__,
  androidChannelId: "high_priority_notifications",
  androidChannelName: "High Priority Notifications",
  autoInitialize: true,
  serverEndpoint: "https://api.myapp.com/tokens",
  metadata: {
    userId: "user123",
    appVersion: "1.0.0",
  },
};

const pushBase = PushBase.getInstance(config);

API Reference

Core Methods

getInstance(config?: PushBaseConfig): PushBase

Returns the singleton instance of PushBase.

const pushBase = PushBase.getInstance({
  debug: true,
  autoInitialize: true,
});

initialize(): Promise<void>

Initializes the SDK and sets up Firebase messaging.

await pushBase.initialize();

requestPermissions(): Promise<PermissionStatus>

Requests push notification permissions from the user.

const permissions = await pushBase.requestPermissions();
console.log("Granted:", permissions.granted);
console.log("Status:", permissions.status);
console.log("Settings:", permissions.settings);

getToken(): Promise<string | null>

Retrieves the current FCM token.

const token = await pushBase.getToken();
if (token) {
  // Send token to your server
  await registerTokenWithServer(token);
}

refreshToken(): Promise<string | null>

Forces a token refresh.

const newToken = await pushBase.refreshToken();

Topic Management

subscribeToTopic(topic: string): Promise<void>

Subscribes to a topic for receiving targeted messages.

await pushBase.subscribeToTopic("news");
await pushBase.subscribeToTopic("user_123");

unsubscribeFromTopic(topic: string): Promise<void>

Unsubscribes from a topic.

await pushBase.unsubscribeFromTopic("news");

Event Listeners

onMessage(handler: MessageHandler): () => void

Listens for foreground messages.

const unsubscribe = pushBase.onMessage((message) => {
  // Handle foreground message
  showInAppNotification(message);
});

// Later, unsubscribe
unsubscribe();

onBackgroundMessage(handler: MessageHandler): () => void

Listens for background messages.

pushBase.onBackgroundMessage((message) => {
  // Handle background message
  updateBadgeCount(message);
});

onTokenRefresh(handler: TokenHandler): () => void

Listens for token refresh events.

pushBase.onTokenRefresh((token) => {
  // Update token on server
  updateTokenOnServer(token);
});

onError(handler: ErrorHandler): () => void

Listens for SDK errors.

pushBase.onError((error) => {
  console.error("PushBase error:", error);
  // Report to crash analytics
  crashlytics().recordError(error);
});

Utility Methods

hasPermissions(): Promise<boolean>

Checks if the app has push notification permissions.

const hasPermissions = await pushBase.hasPermissions();
if (!hasPermissions) {
  // Show permission request UI
}

getInitialNotification(): Promise<PushMessage | null>

Gets the notification that opened the app (if any).

const initialNotification = await pushBase.getInitialNotification();
if (initialNotification) {
  // Handle app launch from notification
  navigateToScreen(initialNotification.data?.screen);
}

getState(): SDKState

Returns the current SDK state.

const state = pushBase.getState();
console.log("Initialized:", state.initialized);
console.log("Token:", state.token);
console.log("Permissions:", state.permissions);

destroy(): void

Cleans up the SDK and removes all listeners.

pushBase.destroy();

Types

PushMessage

interface PushMessage {
  messageId?: string;
  data?: Record<string, string>;
  notification?: {
    title?: string;
    body?: string;
    imageUrl?: string;
    android?: {
      channelId?: string;
      smallIcon?: string;
      color?: string;
      priority?: "default" | "high" | "low" | "max" | "min";
    };
    ios?: {
      badge?: number;
      sound?: string;
      categoryId?: string;
    };
  };
  from?: string;
  collapseKey?: string;
  sentTime?: number;
  ttl?: number;
}

PermissionStatus

interface PermissionStatus {
  granted: boolean;
  status: "authorized" | "denied" | "not_determined" | "provisional";
  settings: {
    alert: boolean;
    badge: boolean;
    sound: boolean;
  };
}

SDKState

interface SDKState {
  initialized: boolean;
  token: string | null;
  permissions: PermissionStatus | null;
  lastError: Error | null;
}

Error Handling

The SDK provides comprehensive error handling with specific error codes:

import { PushBaseError, ErrorCodes } from "@pushbase/react-native";

pushBase.onError((error) => {
  if (error instanceof PushBaseError) {
    switch (error.code) {
      case ErrorCodes.PERMISSION_DENIED:
        // Handle permission denied
        showPermissionDeniedDialog();
        break;
      case ErrorCodes.TOKEN_RETRIEVAL_FAILED:
        // Handle token retrieval failure
        retryTokenRetrieval();
        break;
      case ErrorCodes.FIREBASE_NOT_CONFIGURED:
        // Handle Firebase configuration error
        showConfigurationError();
        break;
      default:
        // Handle other errors
        console.error("Unknown error:", error.message);
    }
  }
});

Error Codes

  • INITIALIZATION_FAILED: SDK initialization failed
  • FIREBASE_NOT_CONFIGURED: Firebase is not properly configured
  • PERMISSION_DENIED: User denied push notification permissions
  • TOKEN_RETRIEVAL_FAILED: Failed to retrieve FCM token
  • TOKEN_REGISTRATION_FAILED: Failed to register token with server
  • TOPIC_SUBSCRIPTION_FAILED: Failed to subscribe to topic
  • TOPIC_UNSUBSCRIPTION_FAILED: Failed to unsubscribe from topic
  • INITIAL_NOTIFICATION_FAILED: Failed to get initial notification
  • NOTIFICATION_DISPLAY_FAILED: Failed to display notification

Advanced Usage

Custom Server Integration

Register tokens with your backend server:

const pushBase = PushBase.getInstance({
  serverEndpoint: "https://api.myapp.com/register-token",
  metadata: {
    userId: getCurrentUserId(),
    deviceId: getDeviceId(),
    appVersion: getAppVersion(),
  },
});

// Token will be automatically sent to your server
// with the metadata when it's retrieved or refreshed
pushBase.onMessage((message) => {
  if (message.data?.deepLink) {
    // Handle deep link navigation
    Linking.openURL(message.data.deepLink);
  }
});

// Handle app launch from notification
const handleInitialNotification = async () => {
  const initialNotification = await pushBase.getInitialNotification();
  if (initialNotification?.data?.deepLink) {
    // Navigate to specific screen
    navigation.navigate(initialNotification.data.screen, {
      id: initialNotification.data.id,
    });
  }
};

React Integration

import React, { useEffect, useState } from "react";
import { PushBase } from "@pushbase/react-native";

const usePushNotifications = () => {
  const [token, setToken] = useState<string | null>(null);
  const [permissions, setPermissions] = useState<PermissionStatus | null>(null);
  const [isInitialized, setIsInitialized] = useState(false);

  useEffect(() => {
    const pushBase = PushBase.getInstance({ debug: __DEV__ });

    const initializePush = async () => {
      try {
        await pushBase.initialize();
        const perms = await pushBase.requestPermissions();
        setPermissions(perms);

        if (perms.granted) {
          const fcmToken = await pushBase.getToken();
          setToken(fcmToken);
        }

        setIsInitialized(true);
      } catch (error) {
        console.error("Push initialization failed:", error);
      }
    };

    initializePush();

    // Set up listeners
    const unsubscribeMessage = pushBase.onMessage((message) => {
      // Handle foreground messages
      console.log("Received message:", message);
    });

    const unsubscribeToken = pushBase.onTokenRefresh((newToken) => {
      setToken(newToken);
    });

    return () => {
      unsubscribeMessage();
      unsubscribeToken();
    };
  }, []);

  return { token, permissions, isInitialized };
};

export default usePushNotifications;

Troubleshooting

Common Issues

  1. Token is null

    • Ensure Firebase is properly configured
    • Check if permissions are granted
    • Verify device has Google Play Services (Android)
  2. Permissions denied

    • Guide users to app settings to enable notifications
    • Explain the value of notifications before requesting
  3. Messages not received

    • Check if the app is in the foreground/background
    • Verify FCM server key configuration
    • Test with Firebase Console first
  4. iOS notifications not showing

    • Ensure APNs certificates are configured
    • Check notification payload format
    • Verify app is not in foreground (iOS doesn't show notifications for foreground apps by default)

Debug Mode

Enable debug mode to see detailed logs:

const pushBase = PushBase.getInstance({
  debug: true, // Enable detailed logging
});

Testing

Use Firebase Console to send test notifications:

  1. Go to Firebase Console → Cloud Messaging
  2. Click "Send your first message"
  3. Enter notification details
  4. Select your app and send

Migration Guide

If you're migrating from direct React Native Firebase usage:

Before (React Native Firebase)

import messaging from "@react-native-firebase/messaging";

// Request permission
const authStatus = await messaging().requestPermission();

// Get token
const token = await messaging().getToken();

// Listen for messages
messaging().onMessage(async (remoteMessage) => {
  console.log("Message:", remoteMessage);
});

// Background messages
messaging().setBackgroundMessageHandler(async (remoteMessage) => {
  console.log("Background Message:", remoteMessage);
});

After (PushBase)

import { PushBase } from "@pushbase/react-native";

const pushBase = PushBase.getInstance();

// Initialize and request permissions
await pushBase.initialize();
const permissions = await pushBase.requestPermissions();

// Get token
const token = await pushBase.getToken();

// Listen for messages
pushBase.onMessage((message) => {
  console.log("Message:", message);
});

pushBase.onBackgroundMessage((message) => {
  console.log("Background Message:", message);
});

Support

For issues and questions: