O state, em React, é onde guardamos os dados do nosso componente; porém, pensar em estados é mais antigo e não exclusivo de React, e fica mais fácil entender o state quando pensamos em ciência da computação, não somente em componentes React.
Quando trabalhamos com programação nós definimos estado o tempo todo. O estado de uma aplicação nada mais é que as informações armazenadas no nosso programa em um determinado tempo.
Ao definirmos um componente contador, em um exemplo simples, o seu estado inicial é 0, e de acordo com que vamos mudando o seu valor, estamos então alterando o estado desse componente.
Vamos entender isso na prática, criando um componente de uma Pokédex que estou desenvolvendo para explicar React de uma maneira prática. O seu componente principal possui dois estados: fechado e aberto. Fechado quando entramos na aplicação e aberto quando clicamos no botão ao centro da Pokédex.
Ambos podem ser entendidos melhor nessa imagem:
Na imagem temos o desenho de uma Pokédex fechada e quando o usuário clicar no centro dela, ela muda de estado para aberta, exibindo uma caixa de busca.
Minha Pokédex foi baseada na imagem que encontrei no project-pokemon.
Para este artigo vamos analisar a parte mais pura da criação do app Pokédex, sem estilos bem definidos e com componentes também ainda não bem definidos, para focarmos somente no state do React. O importante aqui é entender os conceitos e como utilizar os métodos para trabalhar com estados.
Se você quiser olhar o código inicial, seria este aqui, no qual temos o seguinte layout renderizado:
Onde temos uma div para o topo, outra para a parte de baixo da Pokédex e um visor com um botão no meio, e se adicionarmos um tamanho fixo no visor ele cresce, empurrando os demais itens.
Se você quiser seguir este exemplo, pode pegar o CSS aqui e focar no trabalho com os estados no React criando um app com o create-react-app.
Para este artigo eu estou assumindo que você já sabe criar uma aplicação com o create-react-app, portanto, se não souber, confira o e-book sobre criação da primeira aplicação com React da Code Prestige, pois lá o Diego Pinho explica tudo sobre create-react-app bem detalhado.
Definindo o estado inicial de um componente
O estado inicial do componente é definido no seu construtor, então vamos dizer que o estado inicial do nosso App é com o visor é “inativo”, e quando clicarmos no botão do centro da Pokédex, o estado deve mudar para “ativo”, e então adicionamos o tamanho de 420px a div “visor”.
No state do App teremos uma propriedade chamada isVisorActive e ela receberá true ou false, iniciando com o estado false, pois o visor deve iniciar no modo inativo e a Pokédex retraída.
constructor(props) { super(props); this.state = { isVisorActive: false } }
O código inteiro ficaria assim:
import React, { Component } from 'react'; import './App.css'; class App extends Component { constructor(props) { super(props); this.state = { isVisorActive: false } } render() { return ( <div className="pokedex"> <div className="top-bar"></div> <div className="visor"> <button class="visor__action-button"></button> </div> <div className="bottom-bar"></div> </div> ); } }
export default App;
Como dito anteriormente, não estou componentizando tudo bonitinho aqui, então o trabalho foi feito direto no componente App, que é responsável por unir os componentes da tela em aplicações React (não por ter um monte de divs) e com as tags HTML espalhadas, somente para depois criarmos os devidos componentes em outros artigos sobre React.
Se tudo ocorreu bem, temos como resultado aquela primeira imagem da aplicação:
Alterando o estado de um componente
Agora precisamos criar um método para alterar o estado do nosso componente. Para alteração de estado em React, precisamos utilizar o setState. Então criamos um método chamado toggleVisor e sua única função aqui, é mudar o valor de isVisorActive.
toggleVisor = () => { this.setState({ isVisorActive: !this.state.isVisorActive }) }
Vamos colocar um console.log somente para confirmar que está funcionando.
toggleVisor = () => { this.setState({ isVisorActive: !this.state.isVisorActive }) console.log(this.state.isVisorActive) }
E agora precisamos adicionar a chamada para este método em nosso botão de ações.
<button className="visor__action-button" onClick={ this.toggleVisor }> </button>
O código até aqui ficará assim:
class App extends Component { constructor(props) { super(props); this.state = { isVisorActive: false } } toggleVisor = () => { this.setState({ isVisorActive: !this.state.isVisorActive }) console.log(this.state.isVisorActive) } render() { return ( <div className="pokedex"> <div className="top-bar"></div> <div className="visor"> <button className="visor__action-button" onClick={ this.toggleVisor }> </button> </div> <div className="bottom-bar"></div> </div> ); } }
Agora podemos clicar no botão e ver se o console.log está funcionando.
Agora vamos fazer com que nosso visor ganhe o tamanho de 420px quando isVisorActive estiver como true, adicionando a seguinte linha de código na nossa div do visor:
style={{ height: this.state.isVisorActive ? '420px' : '' }}
Ficará assim:
<div className="visor" style={{ height: this.state.isVisorActive ? '420px' : '' }}> <button className="visor__action-button" onClick={ this.toggleVisor }> </button> </div>
Agora, quando clicarmos no botão, o método toggleVisor vai mudar o estado para true e então a div visor ganhará o tamanho de 420px.
A div no estado inicial da nossa aplicação ficará assim:
Com seu atributo style vazio.
Agora, quando clicarmos no botão a mágica acontece!
Nosso visor ganhou o tamanho de 420px.
Podemos tratar, também, o próprio botão de ação da Pokédex, onde: quando o estado do visor estiver como ativo, o botão deve sumir e dar espaço para uma caixa de pesquisa pelo nome do Pokémon.
Para que isso seja possível, de uma maneira legal para nossa aplicação, vamos criar um método chamado renderActionButton, que tratará a lógica de renderização dos componentes.
renderActionButton = () => { if (this.state.isVisorActive) { return ( <input type="text" /> ) } return ( <button className="visor__action-button" onClick={this.toggleVisor}> </button> ) }
E vamos invocar este método no local onde deve estar nossas ações.
render() { return ( <div className="pokedex"> <div className="top-bar"></div> <div className="visor" style={{ height: this.state.isVisorActive ? '420px' : '' }}> { this.renderActionButton() } </div> <div className="bottom-bar"></div> </div> ); }
Agora, quando clicarmos no botão de abertura da Pokédex, teremos a caixa de pesquisa aparecendo.
Conclusão
Trabalhar com estado em React é bem fácil, se comparado com algumas outras ferramentas. Isso não significa que é o melhor ou pior modo, mas que é uma maneira interessante de se pensar.
Utilizando o this.setState e this.state podemos fazer magias e maravilhas em nossos componentes. Porém, ainda teremos que entender o conceito de stateless components e statefull components, pois nem todo componente precisa possuir estado. Isso também não é exclusividade do React; já existe em programação há muito tempo, mas esse assunto ficará para um próximo artigo.
O código final para este exemplo está neste link.
Me acompanhe no Twitter para saber quando eu lançar mais artigos sobre React, neste link.