Carregando trilhass

Carregando trilhass

Esta trilha oferece uma visão prática e aprofundada dos hooks mais importantes do React. Cada seção apresenta a motivação, um exemplo prático, armadilhas comuns e recomendações de uso.
useState, useEffect, useContext, useRef.useMemo, useCallback.useReducer.useLayoutEffect, useImperativeHandle, useDebugValue.Essas regras são fundamentais para que o React mantenha a ordem de chamadas e associe corretamente os estados e efeitos.
O hook useState adiciona estado local a componentes funcionais.
Quando usar:
Exemplo:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Contador: {count}</p>
<button onClick={() => setCount(c => c + 1)}>+</button>
</div>
);
}
Dicas:
setState(prev => newValue).useReducer.Armadilhas:
useEffect executa efeitos colaterais (fetch, subscriptions, timers). Substitui os métodos de ciclo de vida das classes (componentDidMount, componentDidUpdate, componentWillUnmount).
Assinatura básica: useEffect(effect, deps).
Exemplo comum (fetch):
import { useEffect, useState } from 'react';
function UsersList() {
const [users, setUsers] = useState([]);
useEffect(() => {
let mounted = true;
fetch('/api/users')
.then(r => r.json())
.then(data => {
if (mounted) setUsers(data);
});
return () => { mounted = false; };
}, []); // [] -> executa apenas no mount
return (
<ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>
);
}
Dependências:
Cleanup:
Armadilhas:
useContext(MyContext) permite acessar o valor do contexto dentro de um componente funcional.
Quando usar:
Exemplo:
import { createContext, useContext } from 'react';
const ThemeContext = createContext('light');
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button className={theme}>Eu sigo o tema</button>;
}
Dicas:
useRef retorna um objeto mutável cuja propriedade .current persiste entre renders.
Usos comuns:
Exemplo:
import { useRef, useEffect } from 'react';
function TextInputWithFocusButton() {
const inputRef = useRef(null);
return (
<>
<input ref={inputRef} />
<button onClick={() => inputRef.current?.focus()}>Focar</button>
</>
);
}
Dica:
useRef para forçar re-render; se precisa re-renderizar quando o valor muda, use useState.useMemo memoriza o resultado de uma função cara entre renders, reavaliando apenas quando dependências mudam.
Uso:
Exemplo:
import { useMemo } from 'react';
function ExpensiveList({ items }) {
const sorted = useMemo(() => {
// operação cara
return items.slice().sort((a,b) => a.value - b.value);
}, [items]);
return <List items={sorted} />;
}
Dicas:
useMemo é uma otimização; só use quando há evidência de custo.useCallback memoriza uma função, útil quando você passa callbacks para componentes filhos que dependem de igualdade referencial (por exemplo, React.memo).
Exemplo:
import { useCallback, useState } from 'react';
function Parent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
return <Child onClick={handleClick} />;
}
Dicas:
Para estados complexos ou lógica de atualização previsível, useReducer pode ser melhor que múltiplos useState.
Exemplo (contador avançado):
import { useReducer } from 'react';
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<>
<div>{state.count}</div>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
</>
);
}
Dicas:
useContext para criar um store local (padrão similar ao Redux leve).useLayoutEffect roda sincronamente após todas as mutações DOM, antes do navegador pintar. Use quando precisa medir DOM e aplicar mudanças que não devem causar flicker.
Aviso:
useEffect é suficiente.Permite expor uma interface imperativa de um componente quando usado com forwardRef.
Exemplo:
import { forwardRef, useImperativeHandle, useRef } from 'react';
const FancyInput = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => inputRef.current.focus(),
}));
return <input ref={inputRef} />;
});
Use quando for necessário permitir chamadas imperativas a partir do pai.
useDebugValue(value) ajuda a mostrar informações customizadas no React DevTools para custom hooks.
Exemplo:
import { useDebugValue } from 'react';
function useFriendStatus(friendId) {
const status = /* ... */;
useDebugValue(status ? 'online' : 'offline');
return status;
}
Custom hooks são funções que começam com use e permitem reutilizar lógica entre componentes.
Exemplo (useLocalStorage):
import { useState, useEffect } from 'react';
function useLocalStorage(key, initial) {
const [state, setState] = useState(() => {
try {
const raw = localStorage.getItem(key);
return raw ? JSON.parse(raw) : initial;
} catch {
return initial;
}
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(state));
}, [key, state]);
return [state, setState];
}
Boas práticas:
@testing-library/react e @testing-library/react-hooks (ou @testing-library/react + helpers) para montar components que usam hooks.renderHook (se usar @testing-library/react-hooks / @testing-library/react tem utilitários parecidos).Exemplo com @testing-library/react-hooks:
import { renderHook, act } from '@testing-library/react-hooks';
import useCounter from './useCounter';
test('useCounter increments', () => {
const { result } = renderHook(() => useCounter());
act(() => result.current.increment());
expect(result.current.count).toBe(1);
});
React.memo para componentes puros que recebem props estáveis.useMemo e useCallback ajudam quando há re-renderizações desnecessárias causadas por referência de objetos/funções.Context.useEffect (causa bugs silenciosos).useMemo/useCallback prematuramente (complexidade sem ganho).this.state -> useStatecomponentDidMount/componentDidUpdate/componentWillUnmount -> useEffectrefs -> useRefExemplo simples:
Classe:
class Example extends React.Component {
state = { count: 0 };
componentDidMount() { /* ... */ }
render() { return <div>{this.state.count}</div>; }
}
Funcional:
function Example() {
const [count, setCount] = useState(0);
useEffect(() => { /* ... */ }, []);
return <div>{count}</div>;
}
Descrição: Hooks mais importantes do ReactJs.
React Hooks: Aprenda os MAIS IMPORTANTES em 50 Minutos!