devlog.blog

🔍 Como Fazer um Sistema de Busca e Filtro em React (Com Projeto Prático)

✨ Introdução

Você já criou uma lista em React, mas agora quer deixá-la mais interativa e dinâmica com busca em tempo real?

É exatamente isso que vamos fazer aqui!

Neste post, vocĂŞ vai aprender a:

  • Criar um sistema de busca e filtro em React
  • Exibir os dados conforme o usuário digita
  • Deixar a experiĂŞncia rápida, sem carregar novamente da API
  • Aplicar isso em qualquer projeto de listagem (produtos, usuários, tarefas, etc.)

💡 Este post é uma continuação do nosso projeto anterior, onde mostramos como carregar dados de uma API com loading e tratamento de erro.

Clique aqui para ver o Ă­nicio do projeto
Agora, vamos aprimorar adicionando um campo de busca com filtro local.


🛠️ Estrutura do Projeto

Já temos um componente que carrega uma lista de usuários via API:
Agora vamos:

  1. Criar um campo de busca (input)
  2. Adicionar um estado para controlar o valor digitado
  3. Filtrar a lista de usuários antes de exibir

đź§Ş CĂłdigo Completo com Busca e Filtro

import { useState, useEffect } from 'react';

function ListaDeUsuarios() {
  const [usuarios, setUsuarios] = useState([]);
  const [carregando, setCarregando] = useState(true);
  const [erro, setErro] = useState(null);
  const [busca, setBusca] = useState('');

  useEffect(() => {
    async function buscarUsuarios() {
      try {
        const resp = await fetch('https://jsonplaceholder.typicode.com/users');
        const data = await resp.json();
        setUsuarios(data);
      } catch (err) {
        setErro('Erro ao carregar usuários');
      } finally {
        setCarregando(false);
      }
    }

    buscarUsuarios();
  }, []);

  const usuariosFiltrados = usuarios.filter(user =>
    user.name.toLowerCase().includes(busca.toLowerCase())
  );

  if (carregando) return <p>Carregando...</p>;
  if (erro) return <p style={{ color: 'red' }}>{erro}</p>;

  return (
    <div style={{ maxWidth: '600px', margin: '0 auto' }}>
      <h2>Lista de Usuários</h2>

      <input
        type="text"
        placeholder="Buscar por nome..."
        value={busca}
        onChange={(e) => setBusca(e.target.value)}
        style={{ padding: '8px', width: '100%', marginBottom: '20px' }}
      />

      {usuariosFiltrados.length === 0 ? (
        <p>Nenhum usuário encontrado.</p>
      ) : (
        <ul>
          {usuariosFiltrados.map(user => (
            <li key={user.id}>
              <strong>{user.name}</strong> - {user.email}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

export default ListaDeUsuarios;

đź§  Explicando a lĂłgica

ElementoFunção
buscaGuarda o texto digitado no campo de busca
onChangeAtualiza o estado busca em tempo real
filter()Aplica o filtro comparando o nome do usuário com o texto da busca
includes()Verifica se o nome contém o que foi digitado (ignorando maiúsculas)

✅ O filtro é feito localmente, ou seja, rápido e sem nova chamada à API.


🎨 Melhorias que você pode aplicar

  • Filtrar por e-mail, cidade ou qualquer outro campo
  • Tornar o filtro insensĂ­vel a acentos (usando normalize())
  • Adicionar um debounce para evitar re-renderizações excessivas
  • Criar um hook useSearch() reutilizável para outros componentes

📣 Conclusão

Agora você tem um sistema de busca simples, rápido e funcional, integrado a um carregamento assíncrono de dados.

Esse padrĂŁo serve para:

  • Listas de usuários
  • Produtos em e-commerce
  • Gerenciadores de tarefas
  • PainĂ©is administrativos

💡 Quer deixar ainda mais avançado?
No próximo post, vamos aplicar filtros combinados (ex: buscar por nome E cidade) e até criar um hook customizado useSearchFilter() para usar em vários lugares.

Fique ligado — e compartilhe esse conteúdo com seu time ou comunidade dev! 🚀

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *