Notify guides
11 · React Native and Expo

React Native and Expo.

Register the native APNs and FCM tokens, and use the same inbox client as the web.

You still need the APNs key and Firebase service account from iOS push and Android push.


1

Native tokens, not Expo push tokens

Notify talks to Apple and Google directly, so it needs the device’s native token. In Expo use getDevicePushTokenAsync(), not getExpoPushTokenAsync(): an Expo push token only works with Expo’s own push service. Expo builds need a development or production build (not Expo Go) for native tokens.


2

The client

@productcraft/notify-js runs in React Native. Its real-time stream needs a fetch that can stream a response body (expo/fetch, or react-native-fetch-api with text streaming); without one it polls the unread count every 30 seconds. There is no document, so pause it yourself when the app goes to the background.

notify.ts
import { AppState } from "react-native";
import { fetch as expoFetch } from "expo/fetch"; // a fetch that can stream (for real-time)
import { createNotifyClient } from "@productcraft/notify-js";

export const notify = createNotifyClient({
  getToken: () => fetch("https://api.example.com/notify-token", { headers: { authorization: `Bearer ${session()}` } }).then((r) => r.text()),
  fetch: expoFetch as unknown as typeof fetch,
});

// No document in React Native: pause the stream in the background yourself.
AppState.addEventListener("change", (state) => {
  if (state === "active") notify.realtime.resume();
  else notify.realtime.pause();
});

declare function session(): string;

3

Register the device

push.ts
import { Platform } from "react-native";
import * as Notifications from "expo-notifications";
import { notify } from "@/lib/notify"; // the client from the previous sample

export async function registerPush() {
  const { status } = await Notifications.requestPermissionsAsync();
  if (status !== "granted") return;
  // The NATIVE token (APNs or FCM), not an Expo push token.
  const { data: token } = await Notifications.getDevicePushTokenAsync();
  const device = await notify.call((me) =>
    me.devices.register(
      Platform.OS === "ios"
        ? { channel: "apns", token, app_id: "com.example.app", environment: __DEV__ ? "sandbox" : "production" }
        : { channel: "fcm", token, app_id: "example-app-prod" },
    ),
  );
  return device.id; // keep it: unregister on logout
}

Keep the returned device id and unregister it on logout (devices and logout). For the inbox UI, render notify.inbox with your own components, as in the framework-free guide; the React components target the web DOM.