React Native Academy · Aula

Criando um aplicativo de lista de contatos

Combine SectionList, cabeçalhos de seção alfabéticos, um filtro de pesquisa e a atualização por gesto para criar uma tela de contatos realista com rolagem fluida.

Aula 4 de 413 etapas

Criando um aplicativo de lista de contatos é uma aula grátis de React Native Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de React Native Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de React Native Academy inclui 4 aulas no total.

Visão geral do aplicativo: lista de contatos

Nesta lição, você criará uma tela realista de lista de contatos que combina tudo das lições sobre FlatList e SectionList. O aplicativo exibirá os contatos agrupados em ordem alfabética, oferecerá um filtro de pesquisa, permitirá a atualização por gesto de puxar e manterá um desempenho fluido mesmo com centenas de entradas.

Definindo os dados dos contatos

Comece com uma matriz estática de objetos de contato. Em um aplicativo real, esses dados viriam da API de contatos do dispositivo ou de um servidor remoto. Cada contato tem um id, um name e um phone. Um ID numérico ou de texto exclusivo é essencial para o keyExtractor.

const CONTACTS = [
  { id: '1', name: 'Alice Brown', phone: '+1-555-0101' },
  { id: '2', name: 'Andrew Chen', phone: '+1-555-0102' },
  { id: '3', name: 'Bob Davis', phone: '+1-555-0201' },
  { id: '4', name: 'Carol Evans', phone: '+1-555-0301' },
  // ... more contacts
];

Estado do filtro de pesquisa

Adicione uma variável de estado searchQuery e filtre a matriz de contatos antes de agrupá-la. O filtro converte tanto a consulta quanto o nome do contato para letras minúsculas, permitindo uma correspondência que não diferencia maiúsculas de minúsculas. Envolva a filtragem e o agrupamento em useMemo para que sejam recalculados apenas quando os contatos ou a consulta mudarem.

const [searchQuery, setSearchQuery] = useState('');

const filteredContacts = useMemo(() => {
  if (!searchQuery) return CONTACTS;
  return CONTACTS.filter((c) =>
    c.name.toLowerCase().includes(searchQuery.toLowerCase())
  );
}, [searchQuery]);

Agrupando contatos em ordem alfabética

Converta a matriz plana filtrada para o formato de seções do SectionList. Reduza os contatos em um mapa indexado pela primeira letra, depois classifique as chaves e mapeie-as para objetos de seção. Essa transformação é executada dentro de useMemo, junto com o filtro, para produzir um único valor calculado.

const sections = useMemo(() => {
  const map = filteredContacts.reduce((acc, contact) => {
    const letter = contact.name[0].toUpperCase();
    if (!acc[letter]) acc[letter] = [];
    acc[letter].push(contact);
    return acc;
  }, {});
  return Object.keys(map).sort().map((key) => ({
    title: key,
    data: map[key],
  }));
}, [filteredContacts]);

Componente da barra de pesquisa

Renderize um TextInput acima do SectionList como ListHeaderComponent, para que ele role junto com a lista. Vincule-o ao estado searchQuery usando onChangeText. Use a propriedade clearButtonMode no iOS para exibir um botão nativo de limpeza dentro do campo de entrada.

const SearchBar = () => (
  <TextInput
    style={styles.searchBar}
    placeholder='Search contacts...'
    value={searchQuery}
    onChangeText={setSearchQuery}
    clearButtonMode='while-editing'
  />
);

Componente de linha de contato

Crie um componente de linha memorizado usando React.memo para evitar renderizações desnecessárias. A linha exibe as iniciais do contato em um círculo de avatar colorido e, à direita, o nome e o número de telefone. Memorizar o componente de linha é essencial para manter uma rolagem fluida com centenas de contatos.

const ContactRow = React.memo(({ item }) => (
  <View style={styles.row}>
    <View style={styles.avatar}>
      <Text style={styles.initials}>{item.name[0]}</Text>
    </View>
    <View>
      <Text style={styles.name}>{item.name}</Text>
      <Text style={styles.phone}>{item.phone}</Text>
    </View>
  </View>
));

Componente de cabeçalho de seção

O cabeçalho alfabético da seção é uma View simples com a letra. Dê a ele uma cor de fundo distinta e um comportamento fixo, para que permaneça visível enquanto o usuário percorre cada grupo de letras. Mantenha o componente pequeno e memorizado, pois ele é renderizado uma vez por letra.

const SectionHeader = ({ section }) => (
  <View style={styles.sectionHeader}>
    <Text style={styles.sectionTitle}>{section.title}</Text>
  </View>
);

Integração da atualização por gesto de puxar

Simule a atualização introduzindo um estado refreshing. Ao atualizar, limpe a consulta de pesquisa (para que os usuários vejam todos os contatos novamente), aguarde brevemente para simular uma chamada de rede e, então, defina refreshing como false. Em um aplicativo real, você buscaria novamente os dados na API de contatos do dispositivo ou no servidor.

const [refreshing, setRefreshing] = useState(false);

const onRefresh = () => {
  setRefreshing(true);
  setSearchQuery('');
  setTimeout(() => setRefreshing(false), 1000);
};

Estado vazio quando não há resultados

Quando a matriz de seções filtradas estiver vazia (nenhum contato corresponder à pesquisa), exiba um estado vazio informativo usando ListEmptyComponent. Informe ao usuário que nenhum contato corresponde à consulta e sugira limpar a pesquisa. Isso é muito melhor do que exibir uma tela em branco.

const ListEmpty = () => (
  <View style={styles.empty}>
    <Text>No contacts found for '{searchQuery}'</Text>
    <Button title='Clear Search' onPress={() => setSearchQuery('')} />
  </View>
);

Montando a tela completa

Combine todas as partes: SectionList com os dados das seções, renderItem memorizado, renderSectionHeader, keyExtractor, cabeçalhos fixos, atualização por gesto de puxar e ListHeaderComponent para a barra de pesquisa. O resultado é uma tela de contatos com qualidade de produção.

export default function ContactsScreen() {
  return (
    <SectionList
      sections={sections}
      keyExtractor={(item) => item.id}
      renderItem={({ item }) => <ContactRow item={item} />}
      renderSectionHeader={({ section }) => <SectionHeader section={section} />}
      stickySectionHeadersEnabled
      refreshing={refreshing}
      onRefresh={onRefresh}
      ListHeaderComponent={SearchBar}
      ListEmptyComponent={ListEmpty}
    />
  );
}

Navegando até a tela de detalhes de um contato

Permita tocar em cada linha envolvendo o ContactRow em um TouchableOpacity que chama navigation.navigate('ContactDetail', { contactId: item.id }). A tela de detalhes lê o ID de route.params e busca os dados completos do contato, seguindo o padrão do React Navigation que você aprendeu anteriormente.

const ContactRow = React.memo(({ item, onPress }) => (
  <TouchableOpacity onPress={() => onPress(item)} style={styles.row}>
    <View style={styles.avatar}>
      <Text style={styles.initials}>{item.name[0]}</Text>
    </View>
    <View>
      <Text style={styles.name}>{item.name}</Text>
      <Text style={styles.phone}>{item.phone}</Text>
    </View>
  </TouchableOpacity>
));

Verificação rápida

Teste sua compreensão da arquitetura do aplicativo de lista de contatos apresentada nesta lição.

Recapitulação da lição

Nesta lição, você aprendeu a: combinar SectionList, filtragem de pesquisa e useMemo para criar uma tela de contatos eficiente, memorizar componentes de linha com React.memo para manter o desempenho da rolagem e integrar a atualização por gesto de puxar e estados vazios para uma experiência de usuário refinada. A seguir, vamos explorar o gancho useRef e os valores mutáveis.

Grátis para começar

Aprenda JavaScript com um tutor de IA — grátis

Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.

Cursos
30
Aulas
120

Perguntas Frequentes

A aula “Criando um aplicativo de lista de contatos” é grátis?

Sim — o texto completo de “Criando um aplicativo de lista de contatos” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de React Native Academy, atualize para CoddyKit PRO. O curso de React Native Academy inclui 4 aulas no total.

O que vou aprender em “Criando um aplicativo de lista de contatos”?

Combine SectionList, cabeçalhos de seção alfabéticos, um filtro de pesquisa e a atualização por gesto para criar uma tela de contatos realista com rolagem fluida. Você pratica React Native Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar React Native Academy?

Nenhuma experiência prévia é necessária. React Native Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.

Quanto tempo leva a aula “Criando um aplicativo de lista de contatos”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de React Native Academy?

Sim. Cada aula de React Native Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Dados de FlatList, renderItem e keyExtractor
  2. Deslizar para atualizar e carregar mais
  3. SectionList com cabeçalhos
  4. Criando um aplicativo de lista de contatos
← Voltar para React Native Academy