Gestão de Perfil Completa no React Native com Firebase (Auth, Firestore, Storage) e AsyncStorage
Em aplicativos móveis modernos, a persistência de dados e a experiência do usuário (UX) são cruciais. Este artigo analisa o componente TelaPerfil, uma solução robusta em React Native com Firebase para gerenciar perfis de usuário. O código implementa um fluxo completo: autenticação, armazenamento de dados textuais no Firestore, upload de foto no Firebase Storage, e uma estratégia de cache local com AsyncStorage para carregamento instantâneo.
1. Arquitetura e Estratégia de Carregamento Híbrido (Cache + Nuvem)
O componente utiliza o hook useEffect para gerenciar o ciclo de carregamento de dados assim que a tela é montada. A grande vantagem deste código é a sua estratégia de carregamento híbrido para otimizar a UX:
Etapa 1: Carregamento Instantâneo (AsyncStorage)
Antes de fazer qualquer requisição à rede, o código tenta ler os dados do perfil salvos localmente no dispositivo usando o AsyncStorage:
JavaScript
const perfilLocal = await AsyncStorage.getItem(storageKey);
if (perfilLocal) {
const dadosLocais = JSON.parse(perfilLocal);
setPerfil({ ...dadosLocais }); // Preenche o estado instantaneamente
setPhotoUrl(dadosLocais.fotoUrl || null);
setCarregando(false); // Oculta o spinner inicial
}
Isso garante que o usuário veja seus dados imediatamente, mesmo sem conexão com a internet, eliminando a percepção de lentidão.
Etapa 2: Atualização em Segundo Plano (Firestore)
Após exibir os dados locais, o código faz uma requisição assíncrona ao Firestore para obter os dados mais recentes:
JavaScript
const perfilRef = doc(bancoDados, 'users', usuario.uid);
const perfilSnap = await getDoc(perfilRef);
if (perfilSnap.exists()) {
const dados = perfilSnap.data();
// ... processa os dados ...
setPerfil({ ...novosDados }); // Atualiza o estado com dados da nuvem
await AsyncStorage.setItem(storageKey, JSON.stringify(novosDados)); // Atualiza o cache local
}
Se houver diferenças entre os dados locais e os da nuvem, a interface é atualizada silenciosamente, e o cache local é renovado.
2. Gestão da Foto de Perfil (ImagePicker + Storage)
A manipulação da imagem de perfil envolve a interação com a galeria do dispositivo e o upload para a nuvem.
Seleção de Imagem (ImagePicker)
A função selecionarFoto utiliza a biblioteca expo-image-picker:
Solicita permissão de acesso à galeria.
Abre a interface da galeria para o usuário escolher uma imagem.
Permite edição (recorte) e define a qualidade para 0.7 (para otimizar o tamanho do arquivo).
Salva a URI da imagem local no estado localImage para exibição prévia na interface.
Upload e Obtenção da URL (Storage)
O upload real para o Firebase Storage ocorre na função uploadImageAsync, chamada apenas quando o usuário salva o perfil:
JavaScript
const uploadImageAsync = async (uri) => {
const response = await fetch(uri); // Converte a URI local em um blob
const blob = await response.blob();
const imagemRef = ref(armazenamento, `profilePictures/${usuario.uid}/${Date.now()}`); // Referência única
const snapshot = await uploadBytes(imagemRef, blob); // Faz o upload dos bytes
return await getDownloadURL(snapshot.ref); // Retorna a URL pública gerada
};
Esta função transforma a imagem local em dados binários (blob) e os envia para uma pasta específica do usuário no Storage, retornando a URL pública necessária para exibir a imagem posteriormente.
3. Salvamento Consolidador do Perfil
A função salvarPerfil coordena a persistência dos dados em três locais diferentes:
Firebase Storage: Se uma nova imagem local foi selecionada, faz o upload e obtém a nova URL.
Firebase Auth (Profile): Atualiza o displayName (nome completo) e o photoURL no objeto de autenticação do usuário, garantindo que essas informações básicas estejam disponíveis rapidamente em todo o app.
Firebase Firestore: Salva o objeto completo do perfil (endereço, telefone, URL da foto, data de atualização) na coleção 'users', usando setDoc com { merge: true } para criar ou atualizar o documento sem sobrescrever campos não enviados.
AsyncStorage: Atualiza o cache local com os dados finais salvos, garantindo a consistência para o próximo carregamento.
4. Recursos de Interface e UX
O componente implementa padrões de design e interações que melhoram a experiência do usuário:
Feedback de Carregamento: Utiliza ActivityIndicator tanto no carregamento inicial da tela quanto no estado de salvamento (salvando), desativando o botão para evitar cliques duplos.
Modo de Edição: O estado editando controla a propriedade editable dos TextInput e a visibilidade do botão “Alterar Foto”, alternando entre visualização e edição de forma limpa.
Scrollview: O conteúdo é envolto em um ScrollView para garantir que todos os campos do formulário estejam acessíveis em telas de diferentes tamanhos e quando o teclado estiver aberto.
Tipos de Teclado: Configura keyboardType="numeric" para o CEP e keyboardType="phone-pad" para o telefone, facilitando a digitação correta pelo usuário.
5. 📚 Glossário de Comandos Utilizados
⚛️ React & React Native
AsyncStorage: Sistema de armazenamento assíncrono, persistente e chave-valor, usado para cache local no dispositivo.
ImagePicker (Expo): Biblioteca para acessar a câmera e a galeria de fotos do dispositivo.
ScrollView: Componente de container que permite rolar o conteúdo quando ele não cabe na tela.
🔥 Firebase (Auth, Firestore, Storage)
autenticacao.currentUser: Obtém o objeto do usuário atualmente logado.
updateProfile() (Auth): Atualiza as informações básicas do perfil do usuário autenticado (displayName, photoURL).
getDoc() (Firestore): Lê um documento específico do banco de dados.
setDoc() (Firestore): Cria ou substitui um documento. Com { merge: true }, ele atualiza apenas os campos fornecidos.
ref() (Storage): Cria uma referência a um local no Firebase Storage para upload ou download.
uploadBytes() (Storage): Faz o upload de dados binários (blobs) para o local referenciado.
getDownloadURL() (Storage): Obtém a URL pública e persistente de um arquivo armazenado no Storage.
Profissional engajado com as últimas tendências tecnológicas e de gestão, buscando continuamente aprimorar suas competências e compartilhar seu conhecimento.
Publicar comentário