Refazendo o projeto de busca com React, componentes, props e state

Refaça a página de busca usando React, TypeScript, componentes, props, state, Tailwind CSS e dados em JSON.
- #Curso de Frontend
- #Projeto React
- #React
- #TypeScript
- #State
- #Props
- #JSON
- #Tailwind CSS
O que vamos construir
Neste projeto, vamos refazer a página de busca que já criamos com HTML, CSS, JavaScript, Tailwind e JSON, mas agora usando React com TypeScript.
A ideia é manter o mesmo objetivo visual, mas mudar a forma de organizar o código. Agora vamos praticar componentes, props, state, renderização de listas, filtro de dados, TypeScript, Tailwind CSS e dados em JSON.
Estrutura sugerida
Use uma estrutura separando componentes, dados, models e views.
Leia a estrutura como uma divisão por responsabilidade: components guarda peças reutilizáveis, views guarda telas, data ou models guardam dados e tipos, e App organiza o uso dessas partes.
src
components
SearchInput.tsx
ResultCard.tsx
ResultsList.tsx
data
searchResults.json
models
SearchResult.ts
views
SearchView.tsx
App.tsx
main.tsx
index.cssModel, JSON e input
Crie o tipo SearchResult para definir o formato de cada resultado. Depois crie searchResults.json com os dados usados pela busca. SearchInput recebe value e onChange por props e não guarda estado próprio.
O JSON funciona como fonte de dados local. O input recebe o texto digitado. O state guarda esse texto para que o React renderize a tela novamente quando ele mudar.
type SearchInputProps = {
value: string;
onChange: (value: string) => void;
};
export function SearchInput({ value, onChange }: SearchInputProps) {
return (
<input
className="w-full rounded-xl border border-slate-300 px-4 py-3 outline-none focus:border-blue-500"
type="text"
value={value}
onChange={(event) => onChange(event.target.value)}
placeholder="Pesquise por HTML, CSS, JavaScript ou React"
/>
);
}Card e lista de resultados
ResultCard recebe um resultado e mostra na tela. ResultsList usa map para transformar cada item do array em um componente. A propriedade key ajuda o React a identificar cada item da lista.
O card deve receber dados por props. A lista percorre os resultados com map e cria um card para cada item. Assim, a mesma estrutura visual serve para vários registros.
Criando a view principal
SearchView controla a tela, guarda o termo no state e usa useMemo para calcular os resultados filtrados quando o termo muda.
Leia a view principal como a tela que junta tudo: input de busca, estado do termo, filtro dos dados e renderização da lista de cards.
import { useMemo, useState } from "react";
import rawResults from "../data/searchResults.json";
import { SearchInput } from "../components/SearchInput";
import { ResultsList } from "../components/ResultsList";
import type { SearchResult } from "../models/SearchResult";
const results = rawResults as SearchResult[];
export function SearchView() {
const [term, setTerm] = useState("");
const filteredResults = useMemo(() => {
const normalizedTerm = term.toLowerCase().trim();
if (!normalizedTerm) {
return results;
}
return results.filter((result) => {
return (
result.title.toLowerCase().includes(normalizedTerm) ||
result.description.toLowerCase().includes(normalizedTerm)
);
});
}, [term]);
return (
<main className="min-h-screen bg-slate-50 px-4 py-16 text-slate-900">
<section className="mx-auto max-w-2xl">
<h1 className="text-center text-5xl font-bold">Buscador React</h1>
<div className="mt-8">
<SearchInput value={term} onChange={setTerm} />
</div>
<ResultsList results={filteredResults} />
</section>
</main>
);
}Componentização, props e state
Componentização é dividir a interface em partes menores. SearchView controla a tela, SearchInput mostra o campo, ResultsList mostra a lista, ResultCard mostra cada resultado e SearchResult define o formato dos dados.
Props são os dados enviados para componentes. State é a informação que muda; neste projeto, o state principal guarda o texto digitado no campo de busca.
Use state quando o valor muda com interação do usuário. Use props para enviar dados de um componente pai para um componente filho.







