Alura > Cursos de Front-end > Cursos de React > Conteúdos de React > Primeiras aulas do curso React: explore e aprofunde seus conhecimentos nos hooks essenciais

React: explore e aprofunde seus conhecimentos nos hooks essenciais

Estados e efeitos - Apresentação

Introdução aos Hooks do React

Você já se perguntou como surgiram os hooks do React e para que eles servem? Provavelmente, já utilizamos useState e useEffect, mas sabemos como surgiram, quais problemas resolvem e quais problemas podem causar se utilizados de forma inadequada em nossos projetos? Quando devemos usá-los e quando não devemos? Essas são perguntas que certamente já nos fizemos, e é para isso que estamos aqui.

Apresentação do Curso

Sejam muito bem-vindos a este curso de React, Hooks Essenciais, onde nos aprofundaremos teoricamente nos hooks essenciais do React, como useState, useEffect, useContext, useReducer, entre outros.

Audiodescrição: Neilton é um homem de pele negra, com olhos e cabelos escuros. No momento, está usando óculos com armação retangular e uma camisa amarela.

Estrutura e Conteúdo do Curso

O que vamos aprender durante este curso? Este curso é um formato que estamos trazendo para que possamos nos aprofundar teoricamente.

Haverá uma série de vídeos em que cada um abordará um hook específico do React. Vamos entender como esse hook surgiu, sua anatomia, como utilizá-lo, para que serve, quando devemos usá-lo, e quais problemas ele pode resolver ou causar em nossa aplicação.

Após aprendermos sobre o hook, haverá atividades para testar nossos conhecimentos, incluindo atividades de múltipla escolha e uma atividade prática, onde aplicaremos o conhecimento adquirido em um projeto. Não se preocupe, pois disponibilizaremos um gabarito para orientação posterior.

Pré-requisitos e Expectativas

Para participar deste curso, é necessário ter um conhecimento aprofundado de JavaScript e um conhecimento básico de React. É recomendado que já tenhamos criado algumas aplicações em React ao longo de nossa jornada. Isso é importante, pois o objetivo aqui é aprofundar nosso conhecimento nos hooks do React.

Conclusão e Próximos Passos

Estamos muito animados para começar e aprender mais sobre esses hooks incríveis que o React oferece. Nos vemos no próximo vídeo. Até lá!

Estados e efeitos - Por que usamos hooks?

Introdução aos Hooks no React

Quando desenvolvemos aplicações em React, é comum utilizarmos alguns hooks, como useState, useEffect e até mesmo useContext para recuperar o contexto de algo. No entanto, é importante entender como surgiram os hooks, quais problemas eles resolvem nas aplicações React e como utilizá-los da melhor forma possível.

React Antes dos Hooks

Antes de tudo, precisamos compreender como era o React antes dos hooks. Antigamente, utilizávamos uma abordagem mais próxima do paradigma de orientação a objetos, com componentes React criados através de classes, os chamados class components. Nessa época, utilizávamos classes para criar componentes e gerenciar seus estados, o que trazia algumas complexidades para a aplicação. Por exemplo, o ciclo de vida era complicado, exigindo ações manuais quando o componente era montado ou atualizado, além de atualizações de estado. Isso tornava o código mais complexo e menos reutilizável.

Exemplo de Componente com Classes

Vamos observar um exemplo de componente React criado com classes. Temos um componente chamado Contador, que é um class component estendendo React.Component. Ele possui um construtor e métodos de classe, seguindo a abordagem do paradigma de programação orientada a objetos. Era necessário definir o estado e criar métodos para lidar com eventos, como a montagem ou atualização do componente. Se o estado fosse mais complexo, precisávamos criar outros métodos dentro do componente, tornando o código verboso e de difícil reutilização.

class Contador extends React.Component {
  constructor(props) {
    super(props);

    this.state = { count: 0 };
  }

  componentDidMount() {
    document.title = `Contagem: ${this.state.count}`;
  }

  componentDidUpdate() {
    document.title = `Contagem: ${this.state.count}`;
  }

  render() {
    return (
      <div>
        <p>Você clicou {this.state.count} vezes</p>
        <button
          onClick={() => this.setState({ count: this.state.count + 1 })}
        >
          Incrementar
        </button>
      </div>
    );
  }
}

Introdução dos Hooks e Functional Components

A solução para essas dificuldades foi a criação dos hooks. Em 2019, com o lançamento da versão 16.8 do React, a equipe do React mudou de uma abordagem com Class Components para Functional Components. Essa mudança eliminou a necessidade de classes nos componentes, facilitando o uso de estados nas aplicações. Para pessoas desenvolvedoras experientes e iniciantes, essa abordagem funcional tornou o aprendizado do React mais fácil e amigável.

Exemplo de Componente com Hooks

A principal novidade dessa mudança foi a introdução dos hooks. O mesmo componente de classe que vimos anteriormente, em uma versão com Functional Components e hooks, é definido como uma função. Utilizamos o hook useState para lidar com o estado da aplicação, retornando algo semelhante ao JSX, que é parecido com HTML. O hook useState retorna o estado e uma função para atualizá-lo, eliminando a necessidade de gerenciar manualmente o ciclo de vida do componente. Isso simplifica o código e facilita sua reutilização.

import { useState } from "react";

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

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

Vantagens dos Hooks

Os hooks tornam o código mais simples e reutilizável, eliminando a necessidade de classes. Com Functional Components, podemos criar componentes como funções, o que é mais familiar para quem está começando com JavaScript e React. Além disso, os hooks facilitam o uso de estados. Com useState, podemos criar quantos estados quisermos na aplicação, sem a necessidade de criar métodos para atualizá-los.

Anatomia do Hook useState

Vamos analisar a anatomia do hook useState. Antes de entender seu funcionamento, é importante compreender o conceito de variáveis de estado no React. As variáveis de estado diferem das variáveis locais, pois, em re-renderizações, as variáveis locais são perdidas. O React cria novas referências para elas, e a informação anterior é perdida. Já as variáveis de estado permitem que o React lembre de dados entre re-renderizações.

Em uma entrevista de emprego, por exemplo, podemos explicar que variáveis de estado são dados que o React lembra entre re-renderizações. O hook useState recebe um valor inicial como argumento, definindo o estado inicial da aplicação. Ele retorna um estado e uma função para atualizá-lo. O estado é uma variável de estado, que só pode ser atualizada com a função retornada pelo useState, chamada setEstado. Se tentarmos atualizar o estado de outra forma, o React não entenderá a alteração. É uma convenção declarar o nome da variável de estado, como estado, e utilizar a função setEstado para atualizá-la.

const [estado, setEstado] = useState(valorInicial);

Atualização de Estado com useState

Após definir uma função, utilizamos o prefixo set antes do nome do estado. Por exemplo, se tivermos uma variável nome, ela será nome e setNome, e para email, será email e setEmail. Utilizamos a anotação de colchetes para desestruturação de array, que inclui o estado e a função que o altera. Esse é um conhecimento básico de JavaScript necessário para trabalhar com React. Aplicaremos e utilizaremos esses conhecimentos básicos de JavaScript com frequência.

Recapitulando, o estado representa o valor atual, enquanto setEstado é a função usada para alterar esse valor. O valor inicial define o estado inicial. No useState, podemos utilizar tipos como booleanos, strings, números, arrays ou objetos. É importante ter cuidado ao atualizar tipos de dados, especialmente arrays e objetos.

Exemplo Prático de Atualização de Estado

Vamos demonstrar isso com código. Estamos utilizando a plataforma IDX, desenvolvida pelo Google, que permite criar aplicações front-end, back-end e mobile online, sem necessidade de configuração local. Nosso objetivo é analisar exemplos de hooks que estamos estudando teoricamente.

No código do componente, utilizamos useState com count e setCount, passando o valor inicial 0. Criamos uma função handleClick, que chama setCount três vezes. Ao clicar no botão, a função handleClick é chamada, incrementando o contador. No entanto, ao clicar, o contador incrementa de 1 em 1, não de 3 em 3, como esperado.

import { useState } from 'react'

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

  function handleClick() {
    setCount(count + 1);
    setCount(count + 1);
    setCount(count + 1);
  }

  return (
    <>
      <h1>useState()</h1>
      <div className="card">
        <button onClick={handleClick}>
          count is {count}
        </button>
      </div>
    </>
  )
}

export default Contador

Uso de prevState para Atualizações Múltiplas

Isso ocorre porque o React chama a função de atualização de estado apenas uma vez por execução. Para chamar a função mais de uma vez, utilizamos o conceito de estado anterior, ou prevState. Na função handleClick, passamos uma função de callback para setCount, utilizando prevCount para atualizar o estado com base no estado anterior.

setCount(prevCount => prevCount + 1);
setCount(prevCount => prevCount + 1);
setCount(prevCount => prevCount + 1);

Ao recarregar a aplicação e clicar no botão, setCount é chamado três vezes corretamente. Isso acontece porque, ao basear-se no estado anterior, colocamos a execução em uma fila, considerando o estado anterior na próxima atualização. Assim, ao chamar handleClick, conseguimos executar setState mais de uma vez.

Atualização de Objetos no Estado

Outro detalhe importante é quando temos objetos como estado. Objetos podem ser mutados durante a execução do código. Em vez de acessar diretamente as propriedades do objeto, criamos um novo objeto utilizando o spread operator para manter o estado consistente. Isso é válido tanto para objetos quanto para matrizes.

const [form, setForm] = useState({firstName: 'Andy', lastName:'Jones'});

// Ao invés disso:
form.firstName = "Taylor";

// Prefira isso:
setForm({
  ...form,
  firstName: "Taylor",
});

Conclusão e Prática

Se houver dúvidas, podemos utilizar o fórum para esclarecimentos. Deixaremos algumas atividades para praticar o uso do useState, incluindo casos reais apresentados. Nos vemos em breve.

Estados e efeitos - Adicionando efeitos colaterais

Introdução aos Hooks do React

Já devemos ter utilizado alguns hooks do React ao desenvolver nossas aplicações, como useState, useEffect e até mesmo useContext para recuperar o contexto de algo. No entanto, sabemos como surgiram os hooks e quais problemas eles resolvem em nossas aplicações React? E mais, sabemos realmente utilizar esses hooks da melhor forma possível? É isso que vamos descobrir.

React Antes dos Hooks

Antes de tudo, precisamos entender como era o React sem os hooks. Antigamente, utilizávamos uma abordagem mais próxima do paradigma de orientação a objetos. Os componentes React eram criados com classes, os chamados class components. Utilizávamos a classe para criar os componentes e também para gerenciar os estados dos mesmos, o que trazia algumas complexidades para nossa aplicação. Por exemplo, o ciclo de vida era complicado, exigindo que disparássemos ações manualmente quando o componente era montado ou atualizado, além de atualizar o estado de uma certa forma. Isso tornava o código complexo e pouco reutilizável.

Exemplo de Componente de Classe

Vamos observar um componente React criado com classes. Temos um componente chamado de contador, que é um class component. Ele estende algo do React, como React.component, e possui um constructor e métodos da classe, seguindo a abordagem do paradigma de programação orientada a objetos. Precisávamos definir o estado e criar métodos para lidar com eventos, como quando o componente era montado ou atualizado. Se tivéssemos um estado mais complexo, era necessário criar outros métodos dentro do componente para atualizá-lo, o que deixava o código verboso. A reutilização também era difícil, pois precisávamos realizar ações específicas quando o componente era montado ou atualizado. O gerenciamento de estados era complexo, exigindo a criação de métodos adicionais para lógica de atualização de estados.

Introdução dos Hooks

A solução para isso foi a criação dos hooks. A partir de 2019, com o lançamento da versão 16.8 do React, a equipe do React mudou de uma abordagem com Class Components para uma abordagem com Functional Components, que são componentes funcionais definidos por meio de funções. Isso eliminou a necessidade de classes nos componentes, simplificando o uso de estados nas aplicações. Para pessoas desenvolvedoras experientes e iniciantes, essa mudança foi benéfica, tornando o aprendizado do React mais fácil e amigável.

Vantagens dos Hooks

A principal novidade dessa mudança para componentes funcionais foi a introdução dos hooks. O mesmo componente de classe que vimos anteriormente, em uma versão com Functional Components e hooks, tinha uma estrutura diferente. Definíamos o componente contador e utilizávamos um hook do React chamado useState para lidar com o estado da aplicação. Retornávamos algo semelhante ao JSX da aplicação, que se assemelha ao HTML, e o hook useState retornava o estado e uma função para atualizá-lo. Não precisávamos nos preocupar com ações específicas quando o componente era montado, pois tudo era gerenciado pelo React através dos hooks. Isso eliminou a complexidade do código e a necessidade de lidar manualmente com esses aspectos.

Recapitulando os Benefícios dos Hooks

Recapitulando, os hooks tornam o código mais simples e reutilizável. O componente de contador, por exemplo, reduziu bastante de tamanho. Eles eliminam a necessidade de classes, permitindo que criemos componentes como funções, o que é mais amigável para quem está migrando do JavaScript para o React. Além disso, facilitam o uso de estados. Com o useState, podemos criar quantos estados quisermos na aplicação, sem a necessidade de criar métodos para atualizá-los.

Anatomia do Hook useState

Vamos analisar a anatomia do hook useState. Antes de entender como ele funciona, precisamos compreender um conceito importante do React: as variáveis de estado. Elas se diferenciam de variáveis locais, pois, quando definimos uma variável local no React, ela é perdida a cada re-renderização. O React cria novas variáveis locais e referências, perdendo a informação anterior. Com as variáveis de estado, o React lembra dos dados entre re-renderizações. Se formos questionados em uma entrevista de emprego sobre a diferença entre variáveis de estado e variáveis locais, podemos explicar que as variáveis de estado são dados que o React lembra entre re-renderizações.

Funcionamento do useState

Voltando à anatomia do hook, o useState recebe como parâmetro um valor inicial, que define o estado inicial da aplicação. Ele retorna um estado e uma função para atualizá-lo. O estado é uma variável de estado e só pode ser atualizado com a função retornada pelo useState, que é o setEstado. Se tentarmos atualizar um estado do React de outra forma, o React não entenderá a alteração. Portanto, é necessário utilizar o setState.

Convenções de Nomenclatura e Desestruturação

Existe uma convenção para declararmos o nome da variável de estado. No caso, estamos definindo como estado, e a função é definida com o prefixo set antes do nome do estado. Por exemplo, se fosse uma variável nome, seria nome e setNome; para email, seria email e setEmail. Utilizamos a anotação de colchetes, que contém o estado e a função que altera ou atualiza o estado, representando a desestruturação de array. Esse é um conhecimento básico de JavaScript que precisamos ter ao trabalhar com React, pois aplicaremos esses conceitos com frequência.

Exemplos Práticos com useState

Recapitulando, o estado representa o valor atual, enquanto setEstado é a função usada para alterar esse valor. Também definimos um valor inicial para o estado. No useState, o estado pode ser um booleano, uma string, um número, um array ou objetos. Podemos definir o estado inicial com esses tipos primitivos, mas devemos ter cuidado ao atualizar alguns tipos de dados, especialmente arrays e objetos.

Exemplificação com Código

Vamos exemplificar com código. Estamos utilizando a plataforma IDX, desenvolvida pelo Google, onde é possível criar aplicações front-end, back-end e mobile. A IDX funciona como uma IDE no navegador, permitindo que trabalhemos online sem precisar configurar ou baixar programas. Nosso objetivo é analisar exemplos de hooks que estamos estudando teoricamente.

Comportamento do useState em Atualizações

Temos um código de componente React utilizando useState com count, setCount e o valor inicial 0. Criamos uma função handleClick que chama setCount três vezes. Retornamos um título e um botão que, ao ser clicado, chama handleClick e incrementa o contador. A aplicação está rodando na janela "web" do IDX. Ao clicar no contador, ele incrementa de 1 em 1, mesmo que handleClick chame setCount três vezes. Isso ocorre porque o React chama a função de atualização de estado apenas uma vez por execução.

Utilizando o Estado Anterior

Se precisarmos chamar uma função que atualiza o estado mais de uma vez, utilizamos o conceito de estado anterior, ou prevState. Dentro de handleClick, passamos uma função de callback para cada setCount, utilizando prevCount para atualizar o estado com base no estado anterior. Isso coloca a execução em uma fila, considerando o estado anterior na próxima atualização.

Atualização de Estados com Base no Estado Anterior

Ao chamar handleClick, o count é atualizado através de prevCount. Inicialmente, é zero, somando um, fica um. Na segunda execução, soma-se mais um, resultando em dois, e na terceira, soma-se mais um, resultando em três. Assim, conseguimos executar setState mais de uma vez. É importante entender que, para chamar setCount mais de uma vez em uma única execução, devemos nos basear no estado anterior, utilizando a convenção prevCount para clareza e legibilidade.

Atualização Segura de Objetos e Arrays

Outro detalhe importante ao atualizar estados é quando lidamos com objetos e arrays. Objetos podem ser mutados durante a execução do código. Ao invés de acessar diretamente as propriedades do objeto, como form.firstName, e mutar o estado, devemos criar um novo objeto. Utilizamos o Spread Operator para copiar o conteúdo do objeto anterior e atualizamos apenas a parte desejada, como firstName. Essa abordagem é mais segura, garantindo um estado consistente.

Conclusão e Atividades Práticas

Discutimos bastante sobre useState. Caso haja dúvidas, podem ser colocadas no fórum, onde estaremos disponíveis para ajudar. Deixaremos algumas atividades para praticar o uso do useState, incluindo casos reais apresentados durante a aula. Nos vemos em breve.

Sobre o curso React: explore e aprofunde seus conhecimentos nos hooks essenciais

O curso React: explore e aprofunde seus conhecimentos nos hooks essenciais possui 129 minutos de vídeos, em um total de 45 atividades. Gostou? Conheça nossos outros cursos de React em Front-end, ou leia nossos artigos de Front-end.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda React acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas