React Hooks foram introduzidos na versão 16.8 do React e representaram uma mudança significativa na forma como desenvolvemos componentes React. Eles permitem que você use o estado e outros recursos do React sem escrever uma classe.

Por que Hooks foram criados?

Antes dos Hooks, componentes com estado precisavam ser classes. Isso trazia alguns desafios:

  • Classes são mais difíceis de entender e reutilizar
  • A lógica de estado ficava espalhada em vários métodos do ciclo de vida
  • Classes não minificam bem e tornam o hot reloading menos confiável

Hooks resolvem esses problemas permitindo a divisão de um componente em funções menores baseadas em pedaços que são relacionados.

Hooks Básicos

useState

O Hook useState permite adicionar estado a componentes de função:


import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>Você clicou {count} vezes</p>
      <button onClick={() => setCount(count + 1)}>
        Clique aqui
      </button>
    </div>
  );
}
                            

useEffect

O Hook useEffect permite executar efeitos colaterais em componentes funcionais:


import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // Similar a componentDidMount e componentDidUpdate:
  useEffect(() => {
    // Atualiza o título do documento usando a API do browser
    document.title = `Você clicou ${count} vezes`;
  });

  return (
    <div>
      <p>Você clicou {count} vezes</p>
      <button onClick={() => setCount(count + 1)}>
        Clique aqui
      </button>
    </div>
  );
}
                            

useEffect aceita um segundo argumento que controla quando o efeito deve ser executado:


// Este efeito só executa quando count muda
useEffect(() => {
  document.title = `Você clicou ${count} vezes`;
}, [count]);

// Este efeito só executa uma vez (como componentDidMount)
useEffect(() => {
  console.log('Componente montado');
  
  // Função de limpeza (como componentWillUnmount)
  return () => {
    console.log('Componente desmontado');
  };
}, []);
                            

Hooks Adicionais

useContext

O Hook useContext facilita o consumo de contextos:


import React, { useContext } from 'react';
import { ThemeContext } from './theme-context';

function ThemedButton() {
  const theme = useContext(ThemeContext);
  
  return (
    <button style={{ background: theme.background, color: theme.foreground }}>
      Botão com Tema
    </button>
  );
}
                            

useReducer

O Hook useReducer é uma alternativa ao useState para lógica de estado mais complexa:


import React, { 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>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
}
                            

Criando Hooks Customizados

Uma das melhores características dos Hooks é a capacidade de extrair lógica de componentes em funções reutilizáveis.


import { useState, useEffect } from 'react';

function useWindowSize() {
  const [windowSize, setWindowSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight,
  });

  useEffect(() => {
    function handleResize() {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    }
    
    window.addEventListener('resize', handleResize);
    
    // Função de limpeza
    return () => window.removeEventListener('resize', handleResize);
  }, []); // Array vazio significa que só executa na montagem e desmontagem

  return windowSize;
}

// Uso do Hook personalizado
function ResponsiveComponent() {
  const size = useWindowSize();
  
  return (
    <div>
      {size.width > 768 ? (
        <p>Tela grande!</p>
      ) : (
        <p>Tela pequena!</p>
      )}
    </div>
  );
}
                            

Regras dos Hooks

Para usar Hooks corretamente, você precisa seguir duas regras:

  1. Apenas chame Hooks no nível superior. Não chame Hooks dentro de loops, condições ou funções aninhadas.
  2. Apenas chame Hooks de componentes React ou de outros Hooks customizados. Não chame Hooks de funções JavaScript comuns.

Conclusão

Hooks representam uma evolução significativa no ecossistema React, simplificando o código e facilitando o reuso de lógica entre componentes. Se você ainda não começou a usá-los, recomendo fortemente que experimente em seu próximo projeto!