Usando o State do Hook
Hooks são uma nova adição ao React 16.8. Eles permitem que você use o state e outros recursos do React sem escrever uma classe.
A página de introdução usou este exemplo para familiarizar com Hooks:
import React, { useState } from 'react';
function Example() {
// Declarar uma nova variável de state, na qual chamaremos de "count" const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
Vamos começar a aprender sobre Hooks comparando este código com um exemplo equivalente utilizando classe.
Exemplo Equivalente com Classe
Se você já usou classes no React, este código deve parecer familiar:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
O state começa como { count: 0 }
, e aumentamos o state.count
chamando this.setState()
quando o usuário clica no botão. Vamos utilizar trechos dessa classe ao longo da página.
Nota
Você pode estar se perguntando porque estamos usando um counter aqui ao invés de um exemplo mais realista. Isto é pra nos ajudar a focar na API enquanto ainda damos os primeiros passos com Hooks.
Hooks e Componentes de Função
Para lembrar, componentes de função, no React, se parecem com isto:
const Example = (props) => {
// Você pode usar Hooks aqui!
return <div />;
}
ou isto:
function Example(props) {
// Você pode usar Hooks aqui!
return <div />;
}
Você pode ter conhecido estes exemplos como “componentes sem estado”. Nós estamos introduzindo a habilidade de utilizar o state do React neles, portanto preferimos o nome “componentes de função”.
Hooks não funcionam dentro de classes. Mas você pode usá-los em vez de escrever classes.
O que é um Hook?
Nosso novo exemplo começa importando o useState
Hook do React:
import React, { useState } from 'react';
function Example() {
// ...
}
O que é um Hook? Um Hook é uma função especial que te permite utilizar recursos do React. Por exemplo, useState
é um Hook que te permite adicionar o state do React a um componente de função. Vamos aprender outros Hooks mais tarde.
Quando eu deveria usar um Hook? Se você escreve um componente de função e percebe que precisa adicionar algum state para ele, anteriormente você tinha que convertê-lo para uma classe. Agora você pode usar um Hook dentro de um componente de função existente. Vamos fazer isso agora mesmo!
Nota:
Existem algumas regras especiais sobre onde você pode ou não utilizar Hooks dentro de um componente. Vamos aprender elas nas Regras dos Hooks.
Declarando uma Variável State
Em uma classe, inicializamos o state count
para 0
definindo this.state
para { count: 0 }
no construtor:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 }; }
Em um componente de função, não temos this
, portanto não podemos definir ou ler this.state
. Em vez disso, chamamos o Hook useState
dentro do nosso component:
import React, { useState } from 'react';
function Example() {
// Declarar uma nova variável de state, na qual chamaremos de "count" const [count, setCount] = useState(0);
O que o useState
faz? Ele declara um variável state. Nossa variável é chamada de count
mas poderíamos chamar de qualquer coisa, como banana
. Esta é uma maneira de “preservar” alguns valores entre as chamadas de funções — useState
é uma nova maneira de usar as mesmas capacidades que o this.state
tem em uma classe. Normalmente, variáveis “desaparecem” quando a função sai mas variáveis de state são preservadas pelo React.
O que passamos para o useState
como argumento? O único argumento para o Hook useState()
é o state inicial. Diferente de classes, o state não tem que ser um objeto. Podemos manter um número ou uma string se for tudo que precisamos. No nosso exemplo, apenas queremos um número para quantas vezes o usuário clicou, então passamos 0 como state inicial para nossa variável. (Se quiséssemos guardar dois valores diferentes no state, chamaríamos useState()
duas vezes.)
O que useState
retorna? Ele retorna um par de valores: o state atual e uma função que atualiza o state. É por isso que escrevemos const [count, setCount] = useState()
. Isto é similar ao this.state.count
e this.setState
em uma classe, exceto o fato de pegá-los em par. Se você não está familiarizado com a sintaxe que usamos, vamos voltar nisso no final dessa página.
Agora que sabemos o que o Hook useState
faz, nosso exemplo deve fazer mais sentido:
import React, { useState } from 'react';
function Example() {
// Declarar uma nova variável de state, na qual chamaremos de "count" const [count, setCount] = useState(0);
Nós declaramos uma variável state chamada count
e definimos ela para 0. O React vai lembrar o valor atual entre cada re-renderização e fornecer o valor mais recente para nossa função. Se quisermos atualizar o count
atual, podemos chamar setCount
.
Nota
Você pode estar se perguntando: Por que é chamado
useState
ao invés decreateState
?“Create” não seria muito preciso porque o state é criado apenas na primeira vez que nosso componente renderiza. Durante as próximas renderizações,
useState
nos da o state atual. Caso contrário, não seria “state” de qualquer maneira! Também tem outro motivo pelo qual nomes de Hook sempre começam comuse
. Vamos aprender o porque depois, nas Regras dos Hooks.
Lendo o State
Quando queremos mostrar o count atual em classe, lemos this.state.count
:
<p>You clicked {this.state.count} times</p>
Em uma função, podemos usar count
diretamente:
<p>You clicked {count} times</p>
Atualizando o State
Em uma classe, podemos chamar this.setState()
para atualizar o state count
:
<button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me
</button>
Na função, já temos setCount
e count
como variáveis então não precisamos do this
:
<button onClick={() => setCount(count + 1)}> Click me
</button>
Recapitulação
Vamos recapitular o que aprendemos linha por linha e checar nosso entendimento.
1: import React, { useState } from 'react'; 2:
3: function Example() {
4: const [count, setCount] = useState(0); 5:
6: return (
7: <div>
8: <p>You clicked {count} times</p>
9: <button onClick={() => setCount(count + 1)}>10: Click me
11: </button>
12: </div>
13: );
14: }
- Linha 1: Importamos o Hook
useState
do React. Ele nos permite manter o state local em um componente de função. - Linha 4: Dentro do componente
Example
, declaramos uma nova variável de state chamando o HookuseState
. Ele retorna um par de valores, no qual damos nomes. Estamos chamando nossa variávelcount
porque ela mantém o número de cliques no botão. Inicializamos como zero passando0
como o único argumento douseState
. O segundo item retornado é a própria função. Ela nos permite atualizar ocount
então nomeamos parasetCount
. - Linha 9: Quando o usuário clica, chamamos
setCount
com um novo valor. O React então vai re-renderizar o componenteExample
, passando o novo valor decount
para ele.
À primeira vista pode parecer muita coisa. Não se apresse! Se você está perdido na explicação, olhe o código acima novamente e tente lê-lo de uma ponta a outra. Prometemos que a partir do momento que você “esquecer” como state funciona em classes e olhar este código com novos olhos irá fazer sentido.
Dica: O que os Colchetes Significam?
Você pode ter percebido os colchetes quando declaramos a variável state:
const [count, setCount] = useState(0);
Os nomes na esquerda não são parte da API do React. Você pode nomear suas próprias variáveis state
:
const [fruit, setFruit] = useState('banana');
Esta sintaxe do JavaScript é chamada de “atribuição via desestruturação”. Significa que estamos fazendo duas novas variáveis fruit
e setFruit
, onde fruit
é definido para o primeiro valor retornado por useState
, e setFruit
é o segundo. É equivalente a este código:
var fruitStateVariable = useState('banana'); // Retorna um par
var fruit = fruitStateVariable[0]; // Primeiro item do par
var setFruit = fruitStateVariable[1]; // Segundo item do par
Quando declaramos uma variável com useState
, ela retorna um par — um array com dois itens. O primeiro item é o valor atual e o segundo é uma função que nos permite atualizá-la. Usar [0]
e [1]
para acessá-las é um pouco confuso porque elas tem um significado específico. É por isto que utilizamos atribuição via desestruturação no lugar.
Nota
Você pode estar curioso como o React sabe qual componente o
useState
corresponde já que não passamos nada comothis
para o React. Vamos responder esta pergunta e muitas outras na seção FAQ.
Dica: Usando Múltiplas Variáveis State
Declarar variáveis de state como par de [something, setSomething]
também é útil porque nos permite dar diferentes nomes para diferentes váriaveis de state se quiséssemos usar mais de uma:
function ExampleWithManyStates() {
// Declarar múltiplas variáveis de state!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
No componente acima, temos age
, fruit
e todos
como variáveis locais e podemos atualizá-las individualmente:
function handleOrangeClick() {
// Similar ao this.setState({ fruit: 'orange' })
setFruit('orange');
}
Você não tem que usar muitas variáveis de state. Elas podem conter objetos e arrays muito bem. Portanto você ainda pode juntar dados relacionados. De qualquer maneira, diferente de this.setState
em classe, ao atualizar uma variável de state, ela sempre é substituida ao invés de incorporada.
Damos mais recomendações em separação de variáveis de state independentes no FAQ.
Próximos Passos
Nesta página aprendemos sobre um dos Hooks fornecido pelo React, chamado useState
. Também, em algumas vezes, vamos nos referir como o “State do Hook”. Ele nos permite adicionar um state local a um componente de função — o que fizemos pela primeira vez!
Também aprendemos um pouco mais sobre o que são Hooks. Hooks são funções que permitem que você utilize recursos do React em componentes de função. Seus nomes sempre começam com use
, e existem mais Hooks que não vimos ainda.
Agora vamos continuar aprendendo o próximo Hook: useEffect
. Ele permite que você execute efeitos colaterais em um componente e é similar ao método de ciclo de vida em classes.