Probabilmente si è arrivati al punto in cui l'app funziona, gli utenti sono stati registrati e il prodotto vuole flussi di ri-engaggio che sembrano nativi. Le notifiche dei carrelli. Le richieste di recensione. Le nuove notifiche di messaggio. Le annunci di rilascio. La prima istintiva è spesso quella di "mettere a punto le notifiche" e poi una settimana dopo si è impegnati a risolvere perché un dispositivo riceve le notifiche, il simulatore sembra registrare bene e nessuno può spiegare perché i tocchi non aprono la schermata giusta.
Le Expo notifiche push sono o piacevolmente semplici o sorprendentemente fragili.
Expo fornisce a React Native un layer pratico sopra APNs e FCM, il che è esattamente il motivo per cui così tanti team lo utilizzano. Ma il gap tra una demo e un'implementazione pronta per la produzione è reale. La gestione del ciclo di vita dei token, il timing delle autorizzazioni, la configurazione dei listener, la progettazione dei payload e la pulizia del backend sono tutti fattori importanti. Se si sta anche inviando cambiamenti logici dell'app con frequenza, la necessità di disciplina operativa diventa ancora più acuta, soprattutto se il lavoro di retention dipende da messaggi affidabili e velocità di rilascio. È lo stesso problema più ampio dietro miglioramento della retention degli utenti dell'app mobile: la consegna è utile solo se l'esperienza utente che la circonda è predittiva.
Indice dei contenuti
- La Fondazione per coinvolgere gli utenti con le notifiche Push di Expo
- Cosa significa prontezza di produzione
- Richiedere la autorizzazione e catturare i token di notifica
- Invia notifiche dal tuo server
- Gestisci le notifiche in arrivo nella tua app
- Pratiche e insidie di produzione
Il fondamento per coinvolgere gli utenti con le notifiche push di Expo
Un Notifica push di Expo La configurazione di una notifica push è attraente per una ragione soprattutto. Rimuove molta complessità della messaggistica nativa che le squadre non vogliono gestire già il primo giorno. Invece di costruire il tubo di APNs e FCM direttamente, puoi lavorare con la porta di ingresso di Expo e concentrarti sul comportamento del prodotto, la routing, l'esperienza UX delle autorizzazioni e la logica dei messaggi backend.
Quell'astrazione non rende le notifiche 'meno reali'. Cambia solo dove va il tuo sforzo di ingegneria.
La servizio è anche veloce abbastanza che il rendimento non è il primo cosa da preoccuparsi. Dal 14 marzo 2023 al 12 giugno 2023, il API di notifica push di Expo ha mostrato un 42 millisecondo tempo di risposta mediano, 273 millisecondo latenza p99, e un tasso di errore medio giornaliero del 0,17% su decine di milioni di messaggi giornalieri, according to Analisi di benchmark di push di Knock Expo API. Ciò dovrebbe rassicurare qualsiasi team che si chiede se Expo è adatto solo per prototipi.
Quello che Expo astrae effettivamente
Quando i team dicono 'Expo push', spesso intendono diversi preoccupazioni separate raccolte insieme:
- Routing del provider: Expo invia messaggi a APNs per iOS e FCM per Android.
- Formato del token: Il tuo server memorizza e invia un token di notifica Expo al posto di gestire inizialmente il trattamento dei token specifici per piattaforma.
- Contratto di richiesta: Invi un payload POST a Expo’s push API al posto di integrare direttamente le API native dei provider.
Ciò è utile, ma crea anche una comune fraintesa. Le squadre a volte suppongono che Expo gestisca ogni problema di consegna. In pratica, molti fallimenti provengono dall'app code, dai token scaduti, dai payload distorti o da una cattiva gestione delle autorizzazioni.
Regola pratica: Considera Expo come un layer di trasporto affidabile, non come un sostituto di un design client e backend solido.
Cosa significa veramente la prontezza di produzione
Un demo funzionante dimostra solo che un dispositivo ha accettato un payload una volta. La prontezza di produzione significa qualcos'altro:
| Preoccupazione | Mindset di demo | Mindset di produzione |
|---|---|---|
| Autorizzazioni | Chiedi subito | Chiedi in contesto, dopo che il valore dell'utente è chiaro |
| Token | Salva una volta | Aggiorna, deduplica, scada e riconcilia |
| Caricamenti | Metti tutto dentro data |
Mantieni i caricamenti piccoli e orientati all'azione |
| Comportamento dell'app | Mostra un avviso | Naviga correttamente e gestisci lo stato in primo piano |
| Operazioni | Test manuali | Ricevute, pulizia, log e gestione degli incidenti |
La differenza tra “invia notifiche” e “notifiche supportano un workflow di prodotto reale”.
Configurazione e impostazione del progetto iniziale
Un sacco di dolore per le push di Expo inizia prima della prima richiesta di autorizzazione. Se la configurazione del tuo progetto è disordinata, il client code può sembrare corretto mentre l'app si comporta in modo inconsistente tra le build.

Inizia con le librerie giuste installate e un ambiente di sviluppo che corrisponde al percorso di build. Se stai lavorando oltre Expo Go, è utile allineare il tuo workflow locale con una configurazione del client di sviluppo Expo personalizzata. custom Expo development client setupPerché il comportamento delle notifiche spesso deve essere verificato in un build che riflette la produzione più da vicino di un rapido esecuzione di test.
Almeno, avrai bisogno di:
In genere, avrai bisogno di:
expo-notificationsPer richieste di autorizzazione, recupero del token, ascolto e presentazione delle notifiche.expo-deviceperché dovresti proteggere la raccolta del tokenDevice.isDevice.
Typical install commands depend on your package manager, but the key is version alignment with your Expo SDK. Don’t mix arbitrary package versions. Let Expo resolve compatible ones.
Aggiungi configurazione a livello di progetto
Mantieni la tua configurazione esplicita. Un minimo app.json or app.config.js Deve riflettere il fatto che le notifiche fanno parte del tuo contratto di app, non un dopo pensiero.
{
"expo": {
"name": "MyApp",
"slug": "my-app",
"plugins": ["expo-notifications"],
"ios": {
"bundleIdentifier": "com.example.myapp"
},
"android": {
"package": "com.example.myapp"
},
"extra": {
"eas": {
"projectId": "your-project-id"
}
}
}
}
Un paio di dettagli contano qui:
- Il nome del pacchetto e l'identificatore del bundle devi sincronizzare l'app che effettivamente distribuisce.
- Il plugin delle notifiche assicura che il progetto nativo riceva la configurazione necessaria durante la compilazione.
- L'ID del progetto EAS è importante quando il recupero del token aspetta che l'app sia associata al progetto Expo corretto.
Imposta un gestore delle notifiche presto
Molti tutorial base aspettano troppo a definire il comportamento delle notifiche. Non farlo. Mettilo vicino all'avvio dell'app affinché il comportamento in primo piano sia prevedibile.
import * as Notifications from 'expo-notifications';
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: true,
}),
});
I team decidono se le notifiche in primo piano dovrebbero mostrare un avviso, riprodurre un suono o influenzare le badge. Il comportamento esatto dipende dal tuo prodotto. Un'app di chat e un'app di pagamento non faranno le stesse scelte.
Se non definisci intenzionalmente il comportamento in primo piano, il tuo team finirà per debuggare le 'notifiche mancanti' che sono state effettivamente ricevute ma mai presentate nel modo in cui il prodotto si aspettava.
Android richiede la configurazione del canale
I canali di notifica Android non sono facoltativi nella pratica. Se li trascuri, le tue notifiche possono apparire disomogenee o non rispettare le aspettative dell'utente.
import { Platform } from 'react-native';
import * as Notifications from 'expo-notifications';
export async function configureAndroidNotifications() {
if (Platform.OS !== 'android') return;
await Notifications.setNotificationChannelAsync('default', {
name: 'Default',
importance: Notifications.AndroidImportance.MAX,
});
}
Configurare questo durante l'inizializzazione dell'app. Poi mantieni stabili gli ID dei canali. Cambiarli con leggerezza rende più difficile ragionare sul comportamento delle notifiche in seguito.
Richiesta di autorizzazione e cattura dei token di push
Questo è il passaggio che molti team copiano da un snippet, poi finiscono per pentirsi.
Le richieste di autorizzazione richiedono un timing, una consapevolezza della piattaforma e un trattamento asincrono disciplinato. La cattura dei token deve avvenire solo su un dispositivo fisico, solo dopo che sono state risolte le autorizzazioni e solo se siete pronti a memorizzare il risultato sul vostro backend immediatamente.

La funzione del client che dovrebbe essere la tua base
Usate una funzione come questa come punto di partenza:
import * as Device from 'expo-device';
import * as Notifications from 'expo-notifications';
import Constants from 'expo-constants';
import { Platform } from 'react-native';
type RegisterResult =
| { ok: true; token: string }
| { ok: false; reason: string };
export async function registerForExpoPushNotificationsAsync(): Promise<RegisterResult> {
if (!Device.isDevice) {
return { ok: false, reason: 'Push notifications require a physical device.' };
}
if (Platform.OS === 'android') {
await Notifications.setNotificationChannelAsync('default', {
name: 'Default',
importance: Notifications.AndroidImportance.MAX,
});
}
const permissions = await Notifications.getPermissionsAsync();
let finalStatus = permissions.status;
if (finalStatus !== 'granted') {
const request = await Notifications.requestPermissionsAsync();
finalStatus = request.status;
}
if (finalStatus !== 'granted') {
return { ok: false, reason: 'Notification permission was not granted.' };
}
const projectId =
Constants.expoConfig?.extra?.eas?.projectId ??
Constants.easConfig?.projectId;
if (!projectId) {
return { ok: false, reason: 'Missing EAS project ID configuration.' };
}
const tokenResponse = await Notifications.getExpoPushTokenAsync({ projectId });
return { ok: true, token: tokenResponse.data };
}
L'ordine conta. Controllate il tipo di dispositivo prima, impostate il comportamento dei canali Android, risolvete le autorizzazioni, verificate la configurazione del progetto, poi richiedete il token Expo.
Perché Device.isDevice non è facoltativo
Questo è uno dei pochi errori che crea molto rumore mentre sembra innocuo. Gli squadre di esperti richiedono la autorizzazione condizionalmente quando Device.isDevice è vero, e un comune tranello è saltare quel guardiano, che porta gli sviluppatori a inviare notifiche a token di simulatore non validi e a incolpare Expo quando il problema è realmente la configurazione dell'applicazione, come descritto in Eagerworks' note di implementazione delle notifiche Expo.
Quello è il motivo per cui il controllo si trova in cima alla funzione. Non nasconderlo dietro un aiutante. Fai che sia evidente.
I risultati del simulatore sono utili per i test di UI. Non sono affidabili per la validazione della registrazione del token di push.
Chiedi la autorizzazione al momento giusto
Don’t ask on the splash screen. Don’t ask before the user understands the value. The best time is usually after a user action that makes notification benefits concrete, such as enabling delivery updates, joining a conversation, or saving a watched item.
Una buona implementazione segue di solito questo flusso:
- Raggiunge un confine significativo di funzionalità.
- Una buona implementazione segue di solito questo flusso:
- La tua app richiede il permesso del sistema.
- Le magazzini delle app conservano il token sul backend immediatamente se viene concesso il permesso.
Quel passaggio finale è dove molte app falliscono. Eseguono il recupero del token, lo registrano localmente e rimandano la registrazione sul backend. In seguito, il supporto non può dire quale dispositivo aveva quale token in un determinato momento.
Ecco un semplice esempio di conservazione del token dopo la registrazione:
export async function enablePushForCurrentUser(userId: string) {
const result = await registerForExpoPushNotificationsAsync();
if (!result.ok) {
return result;
}
await fetch('https://api.example.com/push-tokens', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer user-session-token',
},
body: JSON.stringify({
userId,
token: result.token,
platform: Platform.OS,
}),
});
return result;
}
In un punto successivo del workflow, questo walkthrough è una utile riferimento visivo:
For teams building release-heavy apps, it also helps to think of token registration as part of the app’s operational state, not just part of onboarding. That mindset fits well with broader Invio di Notifiche dal Serverdove il comportamento dell'applicazione può cambiare frequentemente e lo stato del backend deve rimanere sincronizzato.
Ecco un esempio minimale Node-style utilizzando
Once your backend has a valid Expo Push Token, sending a notification is straightforward. The hard part isn’t the request itself. It’s deciding what belongs in the payload and how much trust you place in client state.
Ecco un esempio minimale di stile Node. fetch:
type ExpoPushMessage = {
to: string;
title: string;
body: string;
sound?: 'default' | null;
data?: Record<string, unknown>;
};
export async function sendExpoPushNotification(token: string) {
const message: ExpoPushMessage = {
to: token,
title: 'New review received',
body: 'Tap to open the order details.',
sound: 'default',
data: {
type: 'new_review',
orderId: 'ord_123',
screen: 'OrderDetails',
},
};
const response = await fetch('https://exp.host/--/api/v2/push/send', {
method: 'POST',
headers: {
Accept: 'application/json',
'Accept-encoding': 'gzip, deflate',
'Content-Type': 'application/json',
},
body: JSON.stringify(message),
});
const result = await response.json();
return result;
}
Invio di Notifiche dal Server
Non trattare il payload come un mucchio di rifiuti. Mantieni ogni campo intenzionale.
| Campo | Scopo | Consiglio pratico |
|---|---|---|
to |
Target Expo Token di notifica | Verifica che appartenga al record dispositivo corrente |
title |
Intestazione di notifica | Tienilo breve e leggibile |
body |
Testo visibile principale | Fai chiara l'azione |
sound |
Comportamento del suono del sistema | Usalo con parsimonia per avvisi di alta priorità |
data |
Metadati specifici dell'app | Preferere ID e indizi di percorso rispetto a contenuti ricchi |
La data l'oggetto è dove i flussi di lavoro dei prodotti diventano utili. Puoi passare un tipo e un ID di record, quindi lascia che l'app fetchi i dati più recenti quando l'utente clicca. È più sicuro di inserire direttamente nel payload grandi o sensibili blocchi di dati.
Tenere i payload piccoli e noiosi
According to la guida di Courier alle notifiche di ExpoI payload dovrebbe essere trattato come transitorio, i payload che superano i limiti di dimensione di circa 4 KB possono essere eliminati, e un modello affidabile è inviare payload di metadati piccoli come { "type": "new_review", "id": 123 } piuttosto che grandi JSON o media inline. Quell'indicazione corrisponde a cosa funziona nei sistemi reali. I payload piccoli falliscono meno spesso e invecchiano meglio quando cambia la logica dell'app.
Inviare abbastanza dati per indirizzare l'utente. Fetch il resto dopo che l'app si apre.
Abitudini utili dal lato del server
A una funzione di invio base è sufficiente per i test. Una produzione aggiunge di solito alcune responsabilità aggiuntive:
- Conserva gli sforzi di invio: Salva l'intento di notifica con l'ID utente, il token, il tipo di payload e l'orario.
- Separare la generazione del contenuto dal trasporto: Crea copia del messaggio in un layer e la richiesta Expo API in un altro.
- Gestisci feedback di invalidazione: Se Expo riporta in seguito
DeviceNotRegistered, segnala quel token come obsoleto e fermati di riprovare senza senso. - Utilizza un design adatto per webhook: Se il tuo sistema già emette eventi, invia i trigger delle notifiche attraverso lo stesso tipo di Conserva gli sforzi di invio: utilizzate altrove.
Prima di avviare la debug del client, invia un test push manuale. Se un token riceve una notifica semplice con un payload piccolo, il tuo percorso di trasporto è probabilmente sano. Se non è così, non iniziare cambiando la navigazione code. Inizia validando il token, la forma del payload e lo stato di autorizzazione.
Manipolazione delle Notifiche In Arrivo nell'App
La consegna è solo la metà della funzione. L'app deve fare qualcosa di coerente quando la notifica arriva e quando l'utente la tocca.
Questo significa gestire due momenti separati:
- la notifica arriva mentre l'app è aperta
- l'utente interagisce con la notifica dalla barra dei notifiche o dalla schermata di blocco

Ricezione in primo piano e risposta dell'utente sono eventi diversi
Un setup affidabile include di solito entrambi i listener:
import { useEffect } from 'react';
import * as Notifications from 'expo-notifications';
export function useNotificationObservers(
onForegroundMessage: (notification: Notifications.Notification) => void,
onNotificationTap: (response: Notifications.NotificationResponse) => void
) {
useEffect(() => {
const receivedSub = Notifications.addNotificationReceivedListener(
(notification) => {
onForegroundMessage(notification);
}
);
const responseSub = Notifications.addNotificationResponseReceivedListener(
(response) => {
onNotificationTap(response);
}
);
return () => {
receivedSub.remove();
responseSub.remove();
};
}, [onForegroundMessage, onNotificationTap]);
}
addNotificationReceivedListener Eseguito quando l'app è attiva. addNotificationResponseReceivedListener Eseguito quando l'utente tocca una notifica consegnata. Non combinarli mentalmente. Servono percorsi UX diversi.
Leggi il payload dei dati e naviga intenzionalmente
Ecco un pattern pratico per il gestione dei tap:
type NotificationData = {
type?: string;
orderId?: string;
screen?: string;
};
export function handleNotificationTap(
response: Notifications.NotificationResponse,
navigation: any
) {
const data =
response.notification.request.content.data as NotificationData;
if (data.screen === 'OrderDetails' && data.orderId) {
navigation.navigate('OrderDetails', { orderId: data.orderId });
return;
}
if (data.type === 'new_review') {
navigation.navigate('Inbox');
return;
}
navigation.navigate('Home');
}
Questo pattern rimane resiliente perché il payload contiene indizi di routing, non documenti interi. Se l'ordine è cambiato dal momento in cui la notifica è stata inviata, l'app può recuperare lo stato del server corrente dopo la navigazione.
Una notifica premuta dovrebbe portare a un destino ovvio. Se il percorso di fallback è vago, gli utenti lo notano immediatamente.
Foreground behavior should match user context
Quando l'app è già aperta, mostrare un avviso di sistema a caso può sembrare goffo. A volte il movimento giusto è un banner in-app, un aggiornamento della badge o un aggiornamento silenzioso. Una schermata di posta di supporto potrebbe non richiedere un avviso visibile quando l'utente sta già leggendo quella conversazione.
Il tuo listener in primo piano dovrebbe quindi ramificarsi per rotta e tipo di notifica. Ad esempio:
- Schermo di chat aperto: aggiungi il messaggio e evita un banner ridondante
- Schermo di dashboard aperto: mostra un toast in-app leggero
- Evento critico dell'account: fornisci un trattamento UI più forte
A un approccio semplice si presenta così:
export function handleForegroundNotification(
notification: Notifications.Notification,
currentRouteName: string
) {
const data = notification.request.content.data as { type?: string };
if (currentRouteName === 'ChatThread' && data.type === 'new_message') {
// refresh local thread state
return;
}
// otherwise show your own in-app UI or update badges
}
Se l'app non distingue questi contesti, gli utenti si stancheranno delle notifiche più velocemente, anche se la consegna è tecnicamente corretta.
Pratiche ottimali per la produzione e comuni insidie
La maggior parte delle impostazioni di notifica push Expo rotte non falliscono perché Expo è troppo limitato. Falliscono perché gli squadre assumono che il token è permanente, i payload possono trasportare qualsiasi cosa e gli aggiornamenti dell'app non influenzeranno la logica delle notifiche.
Quell'assunzione non sopravvive alla produzione.

Il token è effimero, non un registro di identità
Un token di notifica Expo è meglio trattato come un affitto, non come un dispositivo di identificazione a vita. I token possono ruotare dopo reinstallazione, cambiamenti di sistema o altri eventi di ciclo di vita. Se un token torna infine DeviceNotRegistered, il tuo backend dovrebbe smettere di trattarlo come attivo.
Un modello backend pratico memorizza:
- ID utente
- piattaforma
- installazione metadata scoping
- token corrente
- timestamp dell'ultima visualizzazione
- stato come ad esempio attivo, scaduto o revocato
Non memorizzare un campo token nell'area dei dati utente e considerare il problema risolto. Gli utenti hanno più dispositivi e i dispositivi cambiano stato.
Refresh strategy matters more than most tutorials admit
La guida ufficiale dell'ecosistema lascia un vero e proprio gap operativo qui. Il contenuto delle notifiche push esistenti Expo spesso non spiega come mantenere la validità dei token. Cicli di revisione della App Store e aggiornamenti OTACiò influisce su come progettare i trigger di aggiornamento. Buoni momenti per riconciliare lo stato del token includono: Documentazione delle notifiche Expo.
Ciò influenza come progettare i trigger di aggiornamento. Buoni momenti per riconciliare lo stato del token includono:
- Avvio dell'app dopo un aggiornamento
- Accedi come utente
- Il cambio delle impostazioni di autorizzazione
- Lavoro di rotazione delle credenziali nel tuo processo di rilascio
- Flussi di recupero dopo i ticket di supporto correlati alle notifiche
La sicurezza e la conformità non devono essere lasciate alla fine dello sprint
Molti tutorial di Expo si concentrano sulla meccanica e trascurano il rischio operativo. Va bene per gli app di hobby. Non è abbastanza per i prodotti di healthcare-adiacente, fintech o commercio regolamentato.
Discussione di Expo delle lacune di notifica di Courier per l'ambito aziendale sottolinea la mancanza di linee guida pratiche per la registrazione del consenso, le tracce di audit e la riduzione dell'esposizione dei payload sensibili. Il takeaway tecnico diretto è semplice:
- Non inserire dati sensibili aziendali nel testo delle notifiche o nei metadati del payload.
- Registra modifiche al consenso sul server.
- Registra quale intento di notifica è stato inviato a quale token.
- Non mettere dati aziendali sensibili nel testo o nel metadati dei payload delle notifiche.
For teams aligning release operations with broader app store e API pratiche di sicurezzapush dovrebbe essere incluso nella stessa disciplina di revisione di autenticazione, analisi e registrazione degli eventi backend.
Le notifiche push sono messaggi destinati agli utenti, ma sono anche un problema di sistemi distribuiti. Trattiamole con la stessa cura che applichiamo allo stato di autenticazione e agli eventi di pagamento.
Cosa funziona di solito e cosa di solito si rompe
| Funziona di solito | Si rompe di solito |
|---|---|
| Richiedere il permesso dopo una chiara spiegazione del valore | Suggerire all'utente all'interno della prima finestra |
| Testare su dispositivi reali | Riscontrare la registrazione del simulatore |
| Memorizzare i token con il contesto del dispositivo | Un token per record utente |
| Invio di piccoli payload di metadati | Inserimento di grandi o sensibili blob |
| Gestione di eventi di tap e di foreground separatamente | Assunzione di tutti i notifiche che seguono un percorso |
| Scadenza di token invecchiati con aggressività | Riproduzione di token morti per sempre |
Una buona configurazione di push di Expo non è complicata. È disciplinata.
Se il tuo team invia spesso modifiche alla logica dell'app e ha bisogno di un controllo più stretto sul comportamento di rilascio, sui rollback e sulla visibilità della consegna. Capgo is worth a look. It helps mobile teams push updates quickly without waiting on store review, which is especially useful when notification flows, routing logic, or client-side fixes need to reach users fast.