This content originally appeared on DEV Community and was authored by Werliton Silva
IndexedDB, WebSocket e React Query trabalhando juntos para um chat moderno, performático e fluido.
Construir um chat moderno e fluido exige mais do que apenas um backend em tempo real. O desafio é entregar velocidade, resiliência offline e sincronização precisa do histórico de mensagens.
Neste artigo, compartilho uma abordagem eficiente usando:
- React + WebSocket para mensagens em tempo real
- IndexedDB para persistir o histórico no client
- React Query para gestão e sincronização do estado
Cenário
Imagine um app de chat onde:
- Ao abrir a conversa, o usuário já vê o histórico instantaneamente
- Mensagens novas aparecem em tempo real
- É possível rolar para carregar mensagens antigas
- Mesmo offline, é possível ver mensagens anteriores
Vamos montar esse fluxo!
1. Armazenamento local com IndexedDB (via Dexie.js)
pnpm add dexie
// db.ts
import Dexie from 'dexie';
export const chatDB = new Dexie('chatDB');
chatDB.version(1).stores({
messages: '++id, chatId, timestamp'
});
2. Carregamento inicial com cache local
const loadCachedMessages = async (chatId: string) => {
return await chatDB.table('messages')
.where('chatId')
.equals(chatId)
.sortBy('timestamp');
};
Ao abrir o chat, exiba essas mensagens imediatamente antes de sincronizar com o servidor.
3. Sincronização com backend (React Query)
import { useQuery } from '@tanstack/react-query';
const fetchLatestMessages = async (chatId: string, after: number) => {
const res = await fetch(`/api/messages?chatId=${chatId}&after=${after}`);
return res.json();
};
const { data: newMessages } = useQuery({
queryKey: ['messages', chatId],
queryFn: () => fetchLatestMessages(chatId, lastLocalTimestamp),
});
E salve essas mensagens também no IndexedDB:
chatDB.table('messages').bulkPut(newMessages);
4. WebSocket para mensagens em tempo real
const socket = new WebSocket('wss://meuapp.com/ws');
socket.onmessage = (event) => {
const message = JSON.parse(event.data);
updateUI(message);
chatDB.table('messages').add(message);
};
5. Scroll infinito para mensagens antigas
Use paginação com timestamp <
para buscar blocos anteriores do histórico, e combine com cache local.
Conclusão
Com IndexedDB + React Query + WebSocket:
- O usuário vê mensagens mesmo offline
- O app é responsivo e parece “instantâneo”
- As mensagens estão sempre sincronizadas
Se você quer entregar uma experiência de chat digna de app nativo, esse é o caminho.
Quer o repositório de exemplo ou ver esse fluxo em funcionamento? Comenta aqui ou me chama no LinkedIn!
This content originally appeared on DEV Community and was authored by Werliton Silva