Continuando a nossa série de posts sobre como criar uma aplicação React, iremos ver neste post como podemos manipular dados em formulários usando React.

    Utilizando e entendendo o state

    O React é desenvolvido com a mentalidade de que não devemos manipular o DOM diretamente, como fazemos com o Jquery utilizando os métodos fornecidos em $, por exemplo. Para modificar qualquer elemento na tela, devemos associar o mesmo ao state, que nada mais é que um objeto criado na inicialização de todo componente React.

    Utilizando o formulário que desenvolvemos, vamos aprimora-lo inicializando o objeto state com as variáveis que utilizaremos para buscar os valores preenchidos nos campos “Descrição” e “Valor”. Para isso, declare o construtor da classe Form da seguinte maneira:

       constructor(props) {
          super(props);
    
          this.state = {
             description: "",
             ammount: 0
          };
       }
    

    Assim como utilizaremos o objeto state para guardar informações referentes aos campos, o mesmo pode ser utilizado para os mais diversos propósitos, como guardar o resultado de um webservice, o resultado de alguma operação calculada, e quaisquer outros tipos de dados.

    Amarrando os inputs com o objeto state

    E no método render iremos atualizar os inputs de “Descrição” e “Valor” para que fiquem desta maneira:

       <form action="">
          <div>
             <input type="text" placeholder="Descrição" value={this.state.description} onChange={this.onDescriptionChange} />
          </div>
    
          <div>
             <input type="text" placeholder="Valor" value={this.state.value} onChange={this.onAmmountChange} />
          </div>
       ...
    

    Note que definir apenas o value do input não será o suficiente para que possamos manipular corretamente as informações que serão exibidas/mostradas para o usuário. No React devemos trabalhar apenas com o state, e por isso que definimos uma função dentro de cada propriedade onChange de ambos os inputs. Esta função será responsável por receber cada alteração de valor digitado pelo usuário e atualizar o objeto state do componente, que por consequência irá atualizar o valor do campo. Se não utilizarmos o método onChange, tudo que o usuário digitar. será ignorado.

    Para atualizar o state com base nas informações recebidas, usaremos a função setState da seguinte maneira:

       onDescriptionChange(event) {
          this.setState({
             description: event.target.value
          });
       }
    
       onAmmountChange(event) {
          this.setState({
             ammount: event.target.value
          });
       }
    

    Após salvar e atualizar a página, ao digitar algum valor nas caixas de texto, note que os métodos onDescriptionChange e onAmmountChange são chamados, porém um erro no console aparece uma ou mais vezes:

    Cannot read property ‘setState’ of undefined

    Isso acontece porque o contexto que o método onChange está sendo chamado, não é o mesmo contexto do componente que instanciamos no React. Caso tenha interesse em saber porque isso acontece com mais detalhes, recomendo que leia este post

    Para solucionar o problema, iremos utilizar o método bind do JavaScript, associando os métodos “onChange” que criamos, com o contexto da classe do componente Form.

       constructor(props) {
          super(props);
    
          this.state = {
             description: "",
             ammount: ""
          };
    
          this.onDescriptionChange = this.onDescriptionChange.bind(this);
          this.onAmmountChange = this.onAmmountChange.bind(this);
       }
    

    Tratando o evento de click com o objeto state

    Da mesma forma que usamos o onChange para a mudança de valor nos inputs do nosso formulário, usaremos o onClick para tratar o evento de click do botão de submit do nosso formulário. Para isso adicione a seguinte função ao componente Form:

       onSaveClick() {
          let transactions = localStorage.getItem('transactions');
    
          if (!transactions)
          transactions = [];
    
          let transaction = {
             description: this.state.description,
             ammount: this.state.ammount
          };
    
          transactions.push(transaction);
    
          localStorage.setItem('transactions', JSON.stringify(transactions));
    
          alert("Lançamento salvo com sucesso.");   
       }
    

    Como não temos um webservice onde essa informação possa ser salva, vamos utilizar o Local Storage do browser.

    Antes de testarmos, defina o evento de onClick no elemento button dentro do método render:

       <button onClick={this.onSaveClick}>Salvar</button>
    

    E faça o bind da função no construtor da classe:

       this.onSaveClick = this.onSaveClick.bind(this);
    

    Até o próximo post!