Os hooks do React, como useState
, useEffect
, useCallback
, e useMemo
, são ferramentas essenciais no arsenal de qualquer desenvolvedor que trabalha com este framework. Eles proporcionam uma maneira elegante e poderosa de gerenciar estado, efeitos colaterais e otimizar o desempenho das aplicações. Através de um exemplo prático, vamos explorar como esses hooks são aplicados em um projeto de busca e categorização de filmes.
useState: Gerenciando o Estado Local com Elegância
O hook useState
permite adicionar estado aos componentes funcionais do React, oferecendo uma alternativa mais simples e direta aos estados em componentes de classe. No projeto exemplo, utilizamos vários estados para controlar diferentes aspectos da interface:
1const [data, setData] = useState<DataProps[]>([]); 2const [loading, setLoading] = useState(true); 3const [search, setSearch] = useState(''); 4const [activeCategory, setActiveCategory] = useState('popular'); 5const [page, setPage] = useState(1);
Cada estado é gerenciado individualmente com sua própria função de atualização, simplificando a manipulação de dados e promovendo a reatividade do componente sem a complexidade do this.setState
.
useEffect: Sincronizando Estado e Efeitos Colaterais
Substituindo os métodos de ciclo de vida de componentes de classe, o useEffect
gerencia efeitos colaterais em componentes funcionais. No nosso projeto, ele é essencial para chamar a função fetchData
sempre que dependências específicas mudam:
1useEffect(() => {
2 fetchData();
3}, [fetchData]);
Isso garante que a função fetchData
seja reexecutada sempre que as variáveis activeCategory
ou page
forem atualizadas, mantendo os dados do componente consistentemente sincronizados com as interações do usuário e as atualizações de estado.
useCallback: Evitando Renderizações Desnecessárias com Funções Memorizadas
O useCallback
memoriza callbacks e garante que eles só sejam recriados quando suas dependências mudam. Isso é extremamente útil para evitar renderizações desnecessárias em componentes que recebem essas funções como props:
1const fetchData = useCallback(async () => {
2 try {
3 const response = await axios.get(
4 `https://api.themoviedb.org/3/movie/${activeCategory}?api_key=${process.env.NEXT_PUBLIC_API_KEY}&page=${page}`,
5 );
6 if (page > 1) {
7 setData((prevData) => [...prevData, ...response.data.results]);
8 } else {
9 setData(response.data.results);
10 }
11 setLoading(false);
12 } catch (error) {
13 console.error(error);
14 }
15}, [activeCategory, page]);
A utilização do useCallback
aqui previne a recriação da função fetchData
a cada renderização, o que é crucial para a performance, especialmente em componentes grandes ou profundamente aninhados.
useMemo: Otimizando Cálculos Pesados
O useMemo
é usado para memorizar valores computados, garantindo que operações pesadas sejam realizadas apenas quando absolutamente necessário. No contexto do nosso projeto, ele seria ideal para calcular os dados filtrados:
1const filteredData = useMemo(() => data.filter((item) => {
2 return item.title.toLowerCase().includes(search.toLowerCase());
3}), [search, data]);
Essa abordagem garante que a operação de filtragem seja executada somente quando o estado search
ou o array data
forem alterados, minimizando o custo computacional e melhorando a resposta da interface ao usuário.
Conclusão
A integração efetiva dos hooks useState
, useEffect
, useCallback
, e useMemo
no desenvolvimento com React não só simplifica a gestão de estado e efeitos colaterais, como também otimiza o desempenho das aplicações. No projeto exemplificado, a interação entre esses hooks mostra uma estratégia robusta e eficiente para criar aplicações dinâmicas e reativas, destacando o poder e a flexibilidade do React.