🔍 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:
- Criar um campo de busca (
input
) - Adicionar um estado para controlar o valor digitado
- 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
Elemento | Função |
---|---|
busca | Guarda o texto digitado no campo de busca |
onChange | Atualiza 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! 🚀