Entendendo Hooks no React

Entendendo Hooks no React

Vamos nos aprofundar com React, e entender o que são os hooks!

Se você conhece bem React, já deve ter visto alguns componentes criados utilizando “classes”. Este era o padrão até a versão 16.7, afinal, alguns recursos do React eram limitados a classe. Os hooks vieram para tirar essa limitação e abrir todos os recursos do React em um formato simples de “função”.

O que antes era assim:

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  handleButtonClick() {
    this.setState({
      count: this.state.count + 1,
    });
  }

  render() {
    return (
      <div>
        <p>Você clicou {this.state.count} vezes</p>
        <button onClick={this.handleButtonClick}>Clique aqui</button>
      </div>
    );
  }
}

Ficou assim:

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

  const handleButtonClick = () => {
    setCount(count + 1);
  };

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

Com o uso dos hooks você pode ter acesso aos estados de um componente e até mesmo a rotina de criação/execução deste mesmo componente de forma muito mais simples e direta. Você pode até mesmo criar o seu próprio hook, segundo a sua necessidade e funcionalidade desejada.

Vamos explorar alguns dos hooks mais utilizados:

useState()

O useState é o hook mais comum do React, afinal, é com ele que temos acesso à funcionalidade de estados de um componente.

Com os estados, você pode mudar o valor de uma variável dinamicamente, após a sua página ter sido renderizada, e o próprio React irá atualizar o valor na página de forma automática.

Para utilizar, é bem simples. Basta chamar a função useState e como parâmetro, enviar o valor default do estado. A função irá te entregar um array com duas variáveis, a primeira sendo o valor atual do estado, e a segunda uma função para mudar o valor do estado:

const [valorAtualDoEstado, funcaoParaMudarOValor] = useState(valorDefault);

useEffect()

O useEffect é outro hook bastante popular e usado diariamente no nosso desenvolvimento com React, com ele, podemos monitorar cada mudança em nosso componente, desde a sua criação, a alguma alteração dentro do componente, ou o seu fim.

Ao utilizar o useEffect em seu componente é esperado que você envie como parâmetro, uma função qualquer, que será utilizada em qualquer nova ação ou efeito dentro do seu componente —importante dizer que o retorno desta função é utilizado ao fim da ação, ou efeito. Além desta função, é esperado no segundo parâmetro um array que contenha as variáveis ou funções a serem observadas —quando vazio, considera-se o próprio componente, no fim, ou no final de seu ciclo de vida.

const funcaoQualquer = () => {
    console.log('Chamado no inicio da ação');

    return () => {
        console.log('Chamado no final da ação');
    }
};

const variaveisObservadas = [];

useEffect(funcaoQualquer, variaveisObservadas);

É bastante comum com o useEffect, por exemplo, ao inicializar o componente realizar um fetch em uma API para buscar os dados a serem utilizados. Também é bastante comum monitorar a mudança de alguma variável para realizar uma ação posterior. Em alguns casos, durante o seu projeto pode ser preciso “desativar” alguma funcionalidade, como, por exemplo, parar de escutar um evento do DOM.

Como criar o seu próprio hook

Um recurso bastante interessante é poder criar seu próprio hook.

Perceba que só é possível utilizar as funcionalidades do React somente dentro de um componente, e não em uma função, por exemplo. Desta forma, ficamos limitados no compartilhamento de código, visto que para reproduzir uma certa funcionalidade preciso de um componente para ela. Mas com essa nova possibilidade, você pode elevar o nível de função comum para o estado de “hook” permitindo compartilhar recursos nativos do React, inclusive outros hooks, em qualquer lugar.

Para criar um hook, basta criar uma função com o prefixo use, assim o React reconhece como um hook e permite o uso de seus recursos dentro dessa função.

Uso bastante o exemplo abaixo em meus projetos, quando preciso buscar o tamanho da página, em largura e altura. Poderíamos utilizar a variável window.innerWidth ou window.innerHeight, mas os valores não serão reativos conforme o que o usuário faz na tela (se diminui ou aumenta o tamanho da página, os valores serão os mesmos). A solução para isso, é criar um state para salvar a largura e a altura, assim terei os valores reativos. Ainda assim, preciso monitorar essa variável para mantê-la sempre atualizada, por isso, utilizo um useEffect para assistir o evento “resize” na página, que irá alterar o valor do meu estado que contém a largura e altura da página, da mesma forma que retiro esse evento quando a página é fechada. Desta forma, consigo retornar em minha função, ou hook, valores reativos da largura e altura de uma página.

export const useWindowSize = () => {
  const [windowSize, setWindowSize] = useState({
    width: 0,
    height: 0,
  });

  const handleSetWindowSize = () => {
    setWindowSize({
      width: window.innerWidth,
      height: window.innerHeight,
    });
  };

  const handleOnPageInit = () => {
    window.addEventListener('resize', handleSetWindowSize);
  };

  const handleOnPageClose = () => {
    window.removeEventListener('resize', handleSetWindowSize);
  };

  useEffect(() => {
    handleSetWindowSize();
    handleOnPageInit();

    return () => handleOnPageClose();
  }, []);

  return windowSize;
};

E para usar, basta chamar:

const { width, height } = useWindowSize();

Como disse no texto “Como organizo meus projetos frontend”, gosto até de utilizar os hooks como use case de um projeto, onde agrupo diversas funcionalidades como fetch de dados e busca de informações no store para ter um código limpo e fácil de ser compartilhado.

Hooks no React são bastante poderosos e você pode e deve abusar deste recurso.

Em nossos projetos da devGo, traremos este conceito a prática. Você pode acompanhar nossos conteúdos participando de nosso canal no Discord e se inscrevendo na nossa newsletter.