Probablemente estás en el punto donde la aplicación funciona, los usuarios han iniciado sesión y el producto ahora quiere flujos de reenganche que se sientan nativos. Recordatorios de la cesta. Prompts de revisión. Alertas de nuevos mensajes. Anuncios de lanzamiento. El primer impulso es a menudo
Es ahí donde las notificaciones de Expo son a la vez sencillas o sorprendentemente frágiles.
Expo ofrece a los equipos de React Native una capa práctica sobre APNs y FCM, lo cual es exactamente por qué tantos equipos la utilizan. Pero la brecha entre una demostración y una implementación lista para producción es real. El ciclo de vida de los tokens, el momento de la autorización, la configuración de los escuchadores, el diseño de los payloads y la limpieza del backend importan. Si también estás enviando cambios lógicos de la aplicación con frecuencia, la necesidad de disciplina operativa se vuelve aún más aguda, especialmente si tu trabajo de retención depende de mensajes confiables y velocidad de lanzamiento. Eso es la misma preocupación más amplia detrás mejora la retención de usuarios de aplicaciones móviles: la entrega solo es útil si la experiencia del usuario alrededor de ella es predecible.
Contenido de la Tabla
- La Fundación para Enganchar a los Usuarios con Notificaciones de Expo
- ¿Qué significa la lista para producción en realidad?
- Solicitar permiso y capturar tokens de notificación
- Solicitar permiso en el momento adecuado
- Hábitos útiles del lado del servidor
- Prácticas recomendadas de producción y trampas comunes
La Fundación para involucrar a los usuarios con las notificaciones de Expo
Un Notificación de Expo La configuración de Expo es atractiva por una razón sobre todas las demás. Elimina una gran cantidad de complejidad de mensajería nativa que los equipos no quieren asumir el día uno. En lugar de construir plumbing de APNs y FCM directo primero, puedes trabajar con la puerta de enlace de Expo y enfocarte en el comportamiento del producto, la ruta, la UX de permisos y la lógica de mensajes de servidor.
Esa abstracción no hace que las notificaciones sean ‘menos reales’. Solo cambia dónde va tu esfuerzo de ingeniería.
El servicio también es lo suficientemente rápido como para que el rendimiento no sea la primera cosa a la que preocuparse. Desde el 14 de marzo de 2023 hasta el 12 de junio de 2023, la notificación de API de Expo mostró un 42 milisegundo de tiempo de respuesta mediano, 273 milisegundo de latencia p99, y un tasa diaria de errores promedio del 0,17% en millones de mensajes diariosde acuerdo a Knock’s Expo push API benchmark analysis. Esto debería tranquilizar a cualquier equipo que se pregunte si Expo solo es adecuado para prototipos.
¿Qué abstrae realmente Expo?
Cuando los equipos dicen "notificación de Expo", a menudo se refieren a varios asuntos separados empaquetados juntos.
- Ruta de proveedor: Expo envía mensajes a APNs para iOS y FCM para Android.
- Formato de token: Su servidor almacena y envía un Expo Push Token en lugar de gestionar el manejo de tokens específicos de plataforma primero.
- Contrato de solicitud: Envía un payload mediante POST a Expo’s push API en lugar de integrar directamente las API de proveedores nativos.
Es útil, pero también crea una confusión común. Los equipos a veces asumen que Expo es responsable de todos los problemas de entrega. En la práctica, muchos fallos provienen de la aplicación code, tokens caducos, payloads malformados o flujo de permisos deficiente.
Regla práctica: Trate a Expo como un capa de transporte confiable, no como un sustituto de un diseño de cliente y servidor sólido.
¿Qué significa realmente la madurez de producción?
Una demostración funcional prueba solo que un dispositivo aceptó un paquete una vez. La preparación para producción significa algo más.
| Preocupación | Mentalidad de demostración | Mentalidad de producción |
|---|---|---|
| Permisos | Pregúntale inmediatamente | Ask in context, after user value is clear |
| Tokens | Guardar una vez | Actualizar, deduplicar, expirar y reconciliar |
| Paquetes | Coloca todo en data |
Mantén los paquetes pequeños y orientados a la acción |
| Comportamiento de la aplicación | Mostrar una alerta | Navega correctamente y maneja el estado de primer plano |
| Operaciones | Pruebas manuales | Recibos, limpieza, registros y manejo de incidentes |
La diferencia entre ‘enviar notificaciones’ y ‘notificaciones que apoyan un flujo de trabajo de producto real’
Configuración y configuración inicial del proyecto
Un montón de dolor de Expo push comienza antes de la primera solicitud de permiso. Si tu configuración de proyecto es desordenada, el cliente code puede parecer correcto mientras la aplicación sigue comportándose de manera inconsistente entre compilaciones.

Start with the right libraries installed and a development environment that matches your build path. If you’re working beyond Expo Go, it helps to align your local workflow with a custom Expo development client setupporque el comportamiento de las notificaciones a menudo necesita ser validado en un build que refleje más de cerca la producción que una rápida ejecución de pruebas.
Al menos, generalmente necesitarás:
En general, necesitarás al menos:
expo-notificationsPara solicitudes de permiso, recuperación de tokens, escuchas y presentación de notificaciones.expo-deviceporque debes proteger la recuperación de tokensDevice.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.
Mantén tu configuración explícita. Un mínimo
Mantén tu configuración explícita. Un mínimo app.json or app.config.js debe reflejar el hecho de que las notificaciones forman parte del contrato de tu aplicación, no un añadido.
{
"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 par de detalles importan aquí:
- Identificadores de paquetes y nombres de paquetes deben coincidir con la aplicación que realmente envías.
- El plugin de notificaciones asegura que el proyecto nativo obtenga la configuración necesaria durante la compilación.
- El ID del proyecto EAS es importante cuando la recuperación de tokens espera que la aplicación esté asociada con el proyecto Expo correcto.
Establece un manipulador de notificaciones temprano
No esperen demasiado para definir el comportamiento de las notificaciones. Colóquenlo cerca del inicio de la aplicación para que el comportamiento en primer plano sea predecible.
import * as Notifications from 'expo-notifications';
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: true,
}),
});
Los equipos deciden si las notificaciones de primer plano deben mostrar una alerta, reproducir un sonido o afectar las insignias. El comportamiento exacto depende de tu producto. Una aplicación de chat y una aplicación de pago no tomarán las mismas decisiones.
Si no defines intencionalmente el comportamiento de primer plano, tu equipo terminará depurando las notificaciones 'faltantes' que se recibieron pero nunca se presentaron de la manera que el producto esperaba.
Android necesita configuración de canal
No son opcionales las canales de notificación de Android en la práctica. Si las omites, tus alertas pueden parecer inconsistentes o no cumplir con las expectativas del usuario.
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,
});
}
Configúrelo durante la inicialización de la aplicación. Luego mantén los IDs de canal estable. Cambiarlos con frecuencia complica la comprensión del comportamiento de las notificaciones en el futuro.
Solicitar Permiso y Capturar Tokens de Push
Muchas veces, los equipos copian este código de un snippet, pero eventualmente se arrepienten.
Las solicitudes de permiso necesitan tener un momento adecuado, conciencia de plataforma y manejo asincrónico disciplinado. La captura de tokens debe ocurrir solo en un dispositivo físico, solo después de resolver las permisiones y solo si estás listo para almacenar el resultado en tu servidor de inmediato.

La función del cliente que debería ser tu punto de partida
Utiliza una función como esta como punto de partida:
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 };
}
La orden importa. Primero verifica el tipo de dispositivo, configura el comportamiento del canal de Android, resuelve los permisos, valida la configuración del proyecto y luego solicita el token de Expo.
¿Por qué? Device.isDevice no es opcional
Este es uno de los pocos errores que crea mucho ruido mientras parece inofensivo. Los equipos expertos solo solicitan permiso condicionalmente cuando Device.isDevice es verdadero, y un error común es omitir ese guardián, lo que lleva a los desarrolladores a enviar notificaciones a tokens de simulador inválidos y culpar a Expo cuando el problema es realmente la configuración de la aplicación, como se describe en Implementación de notificaciones de Expo de Eagerworks.
Eso es por qué el control se encuentra en la parte superior de la función. No lo esconda detrás de un helper. Hágalo obvio.
Los resultados del simulador son útiles para la prueba de UI. No son confiables para validar la inscripción del token de notificación push.
Pida permiso en el momento adecuado
No pregunte en la pantalla de bienvenida. No pregunte antes de que el usuario comprenda el valor. El mejor momento es usualmente después de una acción del usuario que haga los beneficios de las notificaciones concretos, como habilitar las actualizaciones de entrega, unirse a una conversación o guardar un artículo observado.
Una buena implementación sigue generalmente este flujo:
- El usuario alcanza un límite de características significativo.
- App explains the value of notifications in your own UI.
- La aplicación solicita permiso del sistema.
- Las tiendas de aplicaciones almacenan el token en el backend de inmediato si se concede la autorización.
Este último paso es donde muchas aplicaciones fallan. Recuperan el token, lo registran localmente y posponen la inscripción en el backend. Más tarde, el soporte no puede determinar qué dispositivo tenía qué token en qué momento del tiempo.
Aquí hay un ejemplo simple de almacenar el token después de la inscripción:
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;
}
En un paso posterior de este flujo, esta guía es una referencia visual útil:
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 Flujos de trabajo de entrega de aplicaciones de Expodonde el comportamiento de la aplicación cambia con frecuencia y el estado del backend necesita mantenerse sincronizado.
Enviar Notificaciones Desde Tu Servidor
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.
¿Qué debe hacer cada campo del payload? 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;
}
¿Qué debe hacer cada campo del payload
No traten el payload como un contenedor de basura. Mantenga cada campo con un propósito.
| Campo | Objetivo | Consejo práctico |
|---|---|---|
to |
Destino de token de notificación de Expo | Verificar que pertenece al registro del dispositivo actual |
title |
Título de notificación | Manténlo corto y legible |
body |
Texto principal visible | Haz que la acción sea clara |
sound |
Comportamiento de sonido del sistema | Usa con moderación para alertas de alto valor |
data |
Metadatos específicos de la aplicación | Prefer IDs y pistas de ruta sobre contenido rico |
El data objeto es donde los flujos de trabajo de productos se vuelven útiles. Puedes pasar un tipo y un ID de registro, y luego dejar que la aplicación obtenga los datos más recientes cuando el usuario haga clic. Eso es más seguro que insertar grandes o sensibles blobs directamente en el payload.
Mantén los payloads pequeños y aburridos
According to la guía de Courier sobre notificaciones de Expo, los tokens de Expo Push deben tratarse como efímeros, payloads que exceden los límites de tamaño de aproximadamente 4 KB pueden ser descartados, y un patrón confiable es enviar payloads de metadatos pequeños como { "type": "new_review", "id": 123 } en lugar de grandes JSON o medios inline. Ese consejo coincide con lo que funciona en sistemas reales. Los payloads pequeños fallan menos a menudo y envejecen mejor cuando cambian las lógicas de la aplicación.
Envía suficiente datos para dirigir al usuario. Obtén el resto después de que la aplicación se abra.
Hábitos útiles del lado del servidor
A una función de envío básica es suficiente para la prueba. Una producción suele agregar algunas responsabilidades más:
- Almacene intentos de envío: Guarde la intención de notificación con el ID de usuario, token, tipo de carga y fecha de timestamp.
- Separe la generación de contenido de la transportación: Construya copias de mensajes en una capa y la solicitud de Expo API en otra.
- Gestione feedback de invalidación: Si Expo informa más tarde
DeviceNotRegistered, marcar como obsoleto y dejar de intentarlo de manera ciega. - Utilice un diseño amigable con webhooks: Si su sistema ya emite eventos, dirija los disparadores de notificaciones a través del mismo tipo de que utiliza en otros lugares. que utiliza en otros lugares.
Antes de depurar los oyentes del cliente, envíe un testeo de notificación manual primero. Si un token recibe una notificación plana con un payload pequeño, su ruta de transporte probablemente está saludable. Si no, no comience cambiando la navegación code. Comience validando el token, forma del payload y estado de permiso.
Manejo de Notificaciones de Entrada en Tu Aplicación
La entrega es solo la mitad de la característica. La aplicación tiene que hacer algo coherente cuando llega la notificación y cuando el usuario la toca.
Eso significa manejar dos momentos separados:
- la notificación llega mientras la aplicación está abierta
- el usuario interactúa con la notificación desde la bandeja de notificaciones o pantalla de bloqueo

La recepción en primer plano y la respuesta del usuario son eventos diferentes
Un conjunto de configuración confiable suele incluir ambos oyentes:
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 se ejecuta cuando la aplicación está activa. addNotificationResponseReceivedListener se ejecuta cuando el usuario toca una notificación entregada. No los combine mentalmente. Sirven diferentes rutas UX.
Lee el payload de datos y navega intencionalmente
Aquí tienes un patrón práctico para el manejo de toques:
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');
}
Este patrón permanece resistente porque el payload contiene pistas de enrutamiento, no documentos completos. Si el orden ha cambiado desde que se envió la notificación, la aplicación puede recuperar el estado del servidor actual después de la navegación.
Una notificación pulsada debe conducir a un destino obvio. Si tu ruta de fallback es vaga, los usuarios lo notan inmediatamente.
Comportamiento de fondo debe coincidir con el contexto del usuario
Cuando la aplicación ya está abierta, mostrar una alerta de estilo de sistema de manera ciega puede sentirse torpe. A veces, el movimiento correcto es una bandera de aplicación en pantalla, actualización de una insignia o refresco silencioso. Una pantalla de bandeja de entrada de soporte no necesita una alerta visible cuando el usuario ya está leyendo esa conversación.
Su escuchador de primer plano debería ramificarse según la ruta y el tipo de notificación. Por ejemplo:
- Pantalla de chat abierta: añade el mensaje y evita una bandera redundante
- Pantalla de dashboard abierta: muestra una tostada de aplicación en pantalla ligera
- Evento crítico de cuenta: tratamiento de interfaz de usuario más robusto
A un enfoque simple se parece esto:
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
}
Si su aplicación no distingue estos contextos, los usuarios sentirán fatiga de notificaciones más rápido, incluso si la entrega es técnicamente correcta.
Prácticas recomendadas y trampas comunes en producción
La mayoría de las configuraciones de notificaciones de Expo rotas no fallan porque Expo es demasiado limitado. Fallan porque los equipos asumen que el token es permanente, los payloads pueden llevar cualquier cosa y las actualizaciones de la aplicación no afectarán la lógica de las notificaciones.
Esa suposición no sobrevive a la producción.

Los tokens son efímeros, no registros de identidad
Un token de notificación de Expo se trata mejor como un alquiler, no como un dispositivo de identificación a lo largo de la vida. Los tokens pueden rotar después de reinstalar, cambios de sistema operativo o otros eventos de ciclo de vida. Si un token eventualmente regresa DeviceNotRegistered, su servidor debe dejar de tratarlo como activo.
Un modelo de servidor práctico almacena:
- ID de usuario
- plataforma
- instalar metadatos de ámbito
- token actual
- última fecha de visualización
- estado como activo, caducado o revocado
No almacenes un campo de token en la tabla de usuarios y listo. Los usuarios tienen múltiples dispositivos, y los dispositivos cambian de estado.
La estrategia de refresco importa más que la mayoría de los tutoriales admiten
La guía oficial del ecosistema deja un verdadero vacío operativo aquí. El contenido de notificaciones de Expo existente a menudo no explica cómo mantener la validez del token a través de Ciclos de revisión de la App Store y actualizaciones OTAque es especialmente importante para equipos que envían cambios en vivo porque la confiabilidad de la notificación depende del estado actual del token y la sincronización del servidor, como se menciona en Documentación de notificaciones de Expo.
Que afecta cómo diseñan los disparadores de refresco. Buenos momentos para reconciliar el estado del token incluyen:
- lanzamiento de la aplicación después de una actualización
- Iniciar sesión del usuario
- Cambios en la configuración de permisos
- Rotación de credenciales en tu proceso de lanzamiento
- Recovery flows after push-related support tickets
La seguridad y la conformidad no deben estar al final de la iteración
Muchos tutoriales de Expo se centran en la mecánica y omiten el riesgo operativo. Eso está bien para aplicaciones de hobby. No está bien para productos comerciales relacionados con la atención médica, fintech o comercio regulado
Discusión de las brechas de notificaciones de Expo de Courier Destaca una falta de orientación práctica sobre el registro de consentimiento, registros de auditoría y minimización de exposición de paquetes sensibles. La toma de ingeniería directa es simple:
- No incluyas datos de negocio sensibles en el texto o metadatos de notificación
- Actualiza cambios de consentimiento en el servidor.
- Registra qué intención de notificación se envió a qué token
- Utiliza IDs en paquetes y recupera contenido protegido después de abrir la aplicación
For teams aligning release operations with broader app store compliance and API security practicespush debe incluirse en el mismo conjunto de revisión que la autenticación, el análisis y el registro de eventos de backend.
Las notificaciones push son mensajes dirigidos a los usuarios, pero también son un problema de sistemas distribuidos. Trátalos con el mismo cuidado que aplicarías a los estados de autenticación y los eventos de pago.
¿Qué funciona normalmente y qué normalmente se rompe?
| Funciona normalmente | Se rompe normalmente |
|---|---|
| Pedir permiso después de una explicación clara del valor | Mostrar la solicitud en la primera pantalla |
| Probar en dispositivos reales | Confiar en la inscripción del simulador |
| Almacenar tokens con contexto de dispositivo | Un token por registro de usuario |
| Enviar pequeños payloads de metadatos | Insertar grandes o sensibles blobs |
| Tratar eventos de tap y de fondo por separado | Suponer que todas las notificaciones siguen un camino |
| Expirar tokens caducos de manera agresiva | Reintentar tokens muertos para siempre |
Una buena configuración de notificaciones de Expo no es complicada. Es disciplinada.
Si su equipo envía cambios frecuentes en la lógica de la aplicación y necesita un control más estricto sobre el comportamiento de la liberación, los reenvíos y la visibilidad de la entrega. 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.