Pular para o conteúdo principal

React Native e Expo

8 min de leituraAtualizado em 26 out. 2026

O pacote @atalia-ia/react-native-chat leva os SDKs nativos de Android e iOS para o seu app React Native: é o mesmo chat, com os mesmos recursos, chamado pelo JavaScript. Funciona com Expo e com React Native puro.

Não roda no Expo Go

Como qualquer pacote com código nativo, o SDK precisa de um development build: npx expo run:android, npx expo run:ios ou um build do EAS. No Expo Go o pacote não carrega.

Testado com Expo SDK 58 (React Native 0.88), na nova arquitetura.

1. Instalar​

Num app Expo:

npx expo install @atalia-ia/react-native-chat

Num app React Native sem Expo, instale antes o suporte a módulos do Expo (uma vez por projeto) e depois o pacote:

npx install-expo-modules@latest
npm install @atalia-ia/react-native-chat
cd ios && pod install

2. Configurar pelo plugin​

O plugin grava o token do canal e as permissões nos arquivos nativos. Com ele, o SDK já nasce configurado quando o app abre, antes do JavaScript: é isso que faz o toque numa notificação, com o app fechado, abrir a conversa certa.

app.json
{
"expo": {
"plugins": [
["@atalia-ia/react-native-chat", { "channelToken": "<token-do-canal>" }]
]
}
}

O token fica em Configurações › Canais › Editar canal › Instalação › Token do widget, no painel da Atalia. Depois de mudar o plugin, gere os projetos nativos de novo (npx expo prebuild ou o próximo npx expo run:*).

OpçãoPadrãoPara quê
channelTokennenhumToken do canal. Sem ele, chame configure pelo JavaScript
baseUrlhttps://chat.atalia.aiOutra origem: homologação ou o domínio próprio do canal
customDomainfalsetrue quando baseUrl é o domínio próprio vinculado ao canal
cameraPermission"Para enviar fotos no chat de atendimento."Texto do pedido de câmera no iOS. A chave é obrigatória: sem ela o iOS fecha o app quando o visitante escolhe tirar foto
microphonePermission"Para gravar mensagens de voz no chat de atendimento."Texto do pedido de microfone, ou false para não pedir (o chat avisa o visitante)
notificationstrueAndroid 13+: declara a permissão POST_NOTIFICATIONS
notificationIconnenhumAndroid: PNG branco com fundo transparente (96×96) para o ícone das notificações. Veja Notificações push

Sem o plugin (React Native puro), configure pelo JavaScript quando o app inicia. O toque numa notificação com o app fechado só abre a conversa depois desse configure.

App.tsx
import Atalia from '@atalia-ia/react-native-chat';

Atalia.configure('<token-do-canal>');

As opções do configure são as de AtaliaOptions, na referência. Chamar o configure com o plugin já configurado só troca as opções.

3. Abrir o chat​

import Atalia from '@atalia-ia/react-native-chat';

<Button title="Falar com a gente" onPress={() => Atalia.open()} />

Atalia.openConversation(id) abre direto numa conversa. A tela do chat é nativa e abre numa folha que sobe sobre o app (arrastar a alça fecha); presentationStyle: 'fullScreen' no configure abre em tela cheia. No iOS, Atalia.close() fecha.

4. Não lidas e estado​

O hook atualiza sozinho:

import { useAtaliaState } from '@atalia-ia/react-native-chat';

function MenuSuporte() {
const { unreadCount, isIdentified, isChatOpen } = useAtaliaState();
return <Text>Suporte {unreadCount > 0 ? `(${unreadCount})` : ''}</Text>;
}

Para só o número, useAtaliaUnreadCount(). Fora de componente, await Atalia.getState().

5. Identificar o usuário logado​

try {
const contact = await Atalia.identify(tokenDoSeuBackend);
} catch (error) {
console.warn(error.code); // EXPIRED, INVALID_SIGNATURE...
}

// no logout do app:
await Atalia.logout();

O JWT é assinado pelo seu backend com o segredo do canal, nunca no app. Regras e códigos de erro em Identificar o usuário logado.

6. Eventos​

import { useAtaliaEvent } from '@atalia-ia/react-native-chat';

useAtaliaEvent((event) => {
if (event.type === 'messageReceived') analytics.track('mensagem_suporte');
});

Fora de componente, Atalia.addListener(listener) devolve um objeto com remove(). Os eventos estão na referência.

7. Botão flutuante​

Opcional: o SDK não desenha nada sobre o app sem você pedir. O botão fica por cima de todas as telas, com a aparência do painel.

Atalia.showLauncher({ bottomMargin: 72 }); // acima da barra de abas
Atalia.hideLauncher();

As opções (side, horizontalMargin, bottomMargin, text, subtitle, color, collapse, collapseAfter, draggable, dockable, preloadChat) estão na referência e o comportamento, em Botão flutuante. Chamar showLauncher de novo troca as opções.

8. Notificações push​

A regra de quando notificar é da Atalia, como no app nativo: o painel e o comportamento estão em Notificações push. Aqui, o que fazer no projeto React Native.

Qual biblioteca de push usar​

BibliotecaAndroidiOS
@react-native-firebase/messaging (recomendada)SimSim
expo-notificationsSimSó pelo modo webhook

No iOS, a Atalia envia pelo Firebase do app, e o Firebase só entrega a quem registrou o token dele. O expo-notifications entrega o token do APNs, que serve ao seu backend no modo webhook. Use uma das duas bibliotecas: no iOS, as duas tentam tratar as notificações do app.

Com o Firebase​

1. Prepare o Firebase e o painel. No projeto do Firebase, crie o app Android e o app iOS e baixe o google-services.json e o GoogleService-Info.plist. Para o iOS, envie a chave do APNs ao Firebase (passos, aba iOS). No painel da Atalia, ligue as notificações e envie a conta de serviço (passos).

2. Instale as bibliotecas.

npx expo install @react-native-firebase/app @react-native-firebase/messaging expo-build-properties

3. Configure o app.

app.json
{
"expo": {
"android": {
"googleServicesFile": "./google-services.json"
},
"ios": {
"googleServicesFile": "./GoogleService-Info.plist",
"entitlements": { "aps-environment": "development" }
},
"plugins": [
["@atalia-ia/react-native-chat", {
"channelToken": "<token-do-canal>",
"notificationIcon": "./assets/notificacao.png"
}],
"@react-native-firebase/app",
"@react-native-firebase/messaging",
["expo-build-properties", { "ios": { "useFrameworks": "dynamic" } }]
]
}
}
  • googleServicesFile: os arquivos que você baixou do Firebase.
  • aps-environment: liga a capability Push Notifications no iOS, como o Xcode faz. O valor é development; na exportação para o TestFlight e a App Store, a assinatura passa a usar production.
  • useFrameworks: "dynamic": o @react-native-firebase 27 exige no iOS, porque o Firebase só é distribuído pelo Swift Package Manager. Versões anteriores pediam static: siga o que a versão instalada pede.
  • notificationIcon: o ícone pequeno das notificações no Android, um PNG branco com fundo transparente de 96×96. Vale para as notificações que o sistema mostra (app em segundo plano) e para as que o SDK mostra (app aberto). Sem ele, o Android usa o ícone do app, que aparece como um quadrado branco.

Depois de mudar o app.json, gere os projetos nativos de novo: npx expo prebuild --clean.

4. Peça a permissão e ligue ao SDK. Chame quando o app inicia (no componente raiz, por exemplo) ou no momento em que o seu app pede a permissão de notificação.

push.ts
import Atalia from '@atalia-ia/react-native-chat';
import {
getInitialNotification,
getMessaging,
getToken,
onMessage,
onNotificationOpenedApp,
onTokenRefresh,
requestPermission,
} from '@react-native-firebase/messaging';
import { PermissionsAndroid, Platform } from 'react-native';

export async function ligarPush() {
const messaging = getMessaging();

// Sem a permissão nada aparece: no iOS, pelo Firebase; no Android 13 ou mais novo, pelo sistema.
if (Platform.OS === 'ios') await requestPermission(messaging);
else if (Platform.OS === 'android' && Platform.Version >= 33) {
await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
}

Atalia.setPushToken(await getToken(messaging));
onTokenRefresh(messaging, Atalia.setPushToken);

// App aberto: o Firebase não mostra nada sozinho. No Android o SDK mostra (menos com o chat na tela).
onMessage(messaging, async (message) => {
if (!(await Atalia.handleNotification(message))) {
// ...as notificações do seu app
}
});

// Toque com o app em segundo plano e com o app fechado.
onNotificationOpenedApp(messaging, (message) => Atalia.handleNotificationTap(message));
const initial = await getInitialNotification(messaging);
if (initial) Atalia.handleNotificationTap(initial);
}

No iOS, com o app aberto, o @react-native-firebase não mostra a notificação (é o padrão dele), e o handleNotification só atualiza as não lidas. Com o app em segundo plano, quem mostra é o sistema, nas duas plataformas.

Com o expo-notifications​

No Android, o expo-notifications também usa o Firebase: coloque o google-services.json em android.googleServicesFile. O ícone pode vir do plugin dele, que grava o mesmo ícone que o SDK usa:

app.json
["expo-notifications", { "icon": "./assets/notificacao.png" }]
push.ts
import Atalia from '@atalia-ia/react-native-chat';
import * as Notifications from 'expo-notifications';
import { Platform } from 'react-native';

// App aberto: sem banner quando a notificação é da Atalia e o chat já está na tela.
Notifications.setNotificationHandler({
handleNotification: async (notification) => {
const show = await Atalia.shouldShowNotification(notification);
return { shouldShowBanner: show, shouldShowList: show, shouldPlaySound: show, shouldSetBadge: false };
},
});

export async function ligarPush() {
const { granted } = await Notifications.requestPermissionsAsync();
if (!granted) return;

const { data } = await Notifications.getDevicePushTokenAsync();
if (Platform.OS === 'android') Atalia.setPushToken(data);
else Atalia.setAPNsToken(data, __DEV__ ? 'sandbox' : 'production'); // modo webhook

Notifications.addNotificationResponseReceivedListener((response) => Atalia.handleNotificationTap(response));
const last = await Notifications.getLastNotificationResponseAsync();
if (last) Atalia.handleNotificationTap(last);
}

Comportamento​

handleNotification, handleNotificationTap e shouldShowNotification aceitam o objeto que cada biblioteca entrega (a RemoteMessage do Firebase, a Notification ou a resposta do expo-notifications) ou só o data. Notificação de outra origem devolve false (ou true, no shouldShowNotification): trate como as suas.

O número no ícone, a limpeza das notificações lidas e o comportamento no login e no logout são os do SDK nativo: veja Notificações push. No iOS, appBadge: false no configure deixa o número no ícone com o app.

Para testar, deixe o app em segundo plano e use Enviar teste na lista Aparelhos com o app, no painel.

Testar com o app de exemplo​

O repositório tem um app Expo em react-native/example, com o token do canal numa variável de ambiente:

cd react-native && npm install
cd example && npm install
ATALIA_CHANNEL_TOKEN=<token-do-canal> npx expo run:android