Tutorial Reagir, parte 17: O quinto estágio do trabalho em um aplicativo TODO, modificando o estado do componente

Na parte de hoje da tradução do curso React, sugerimos que você conclua a próxima tarefa prática e apresente à sua atenção uma história sobre como modificar o estado dos componentes do React.

imagem

Parte 1: visão geral do curso, razões para a popularidade do React, ReactDOM e JSX
Parte 2: componentes funcionais
Parte 3: arquivos de componentes, estrutura do projeto
Parte 4: componentes pai e filho
Parte 5: início do trabalho em um aplicativo TODO, noções básicas de estilo
Parte 6: sobre alguns recursos do curso, JSX e JavaScript
Parte 7: estilos embutidos
Parte 8: trabalho contínuo na aplicação TODO, familiaridade com as propriedades dos componentes
Parte 9: propriedades do componente
Parte 10: Workshop sobre como trabalhar com propriedades e estilo de componentes
Parte 11: geração dinâmica de marcação e método de matrizes de mapas
Parte 12: workshop, terceira etapa do trabalho em uma aplicação TODO
Parte 13: componentes baseados em classe
Parte 14: workshop sobre componentes baseados em classe, status dos componentes
Parte 15: oficinas de saúde componentes
Parte 16: a quarta etapa do trabalho em um aplicativo TODO, manipulação de eventos
Parte 17: quinta etapa do trabalho em um aplicativo TODO, modificando o estado dos componentes
Parte 18: a sexta etapa do trabalho em um aplicativo TODO
Parte 19: métodos do ciclo de vida dos componentes
Parte 20: a primeira lição sobre renderização condicional
Parte 21: segunda lição e workshop sobre renderização condicional
Parte 22: sétima etapa do trabalho em um aplicativo TODO, baixando dados de fontes externas
Parte 23: primeira lição sobre como trabalhar com formulários
Parte 24: Segunda lição sobre formulários
Parte 25: Workshop sobre como trabalhar com formulários
Parte 26: arquitetura do aplicativo, padrão Container / Component
Parte 27: projeto do curso

Lição 31. Oficina. Aplicação TODO. Estágio número 5


Original

▍Job


Ao iniciar nosso aplicativo Todo, você pode perceber que uma notificação é exibida no console indicando que nós, configurando a propriedade checked de um elemento no componente TodoItem , não fornecemos um mecanismo para interagir com esse elemento na forma de um onChange eventos onChange . Ao trabalhar com a interface do aplicativo, isso resulta no fato de que os sinalizadores exibidos na página não podem ser verificados ou desmarcados.

Aqui você está convidado a equipar um elemento do tipo de checkbox de checkbox do componente TodoItem com um manipulador de eventos TodoItem , que, nesta fase do trabalho, é suficiente para apresentar na forma de uma função que gera algo para o console.

▍Solução


Aqui está a TodoItem código do componente TodoItem agora, armazenado no arquivo TodoItem.js :

 import React from "react" function TodoItem(props) {   return (       <div className="todo-item">           <input type="checkbox" checked={props.item.completed}/>           <p>{props.item.text}</p>       </div>   ) } export default TodoItem 

É isso que o console exibe quando o aplicativo é iniciado.


Notificação do console

Ao mesmo tempo, as bandeiras não respondem aos nossos efeitos.

Para se livrar dessa notificação e preparar o projeto para mais trabalhos, basta atribuir um onChange eventos onChange ao elemento checkbox . Aqui está o que parece no código:

 import React from "react" function TodoItem(props) {   return (       <div className="todo-item">           <input               type="checkbox"               checked={props.item.completed}               onChange={() => console.log("Changed!")}           />           <p>{props.item.text}</p>       </div>   ) } export default TodoItem 

Aqui, como manipulador, usamos uma função simples que gera a palavra Checked! no console Checked! . Ao mesmo tempo, clicar nos sinalizadores não leva a uma alteração no estado deles, mas a notificação do console, como pode ser visto na figura a seguir, desaparece.


Os sinalizadores ainda não estão funcionando, mas a notificação do console desapareceu

Essa pequena alteração feita no aplicativo nos permitirá, após lidarmos com a alteração no estado dos componentes, fazer com que as caixas de seleção funcionem corretamente.

Lição 32. Alterando o estado dos componentes


Original

Vamos começar com um aplicativo padrão criado usando create-react-app App.js create-react-app , no arquivo App.js que contém o seguinte código:

 import React from "react" class App extends React.Component {   constructor() {       super()       this.state = {           count: 0       }   }     render() {       return (           <div>               <h1>{this.state.count}</h1>               <button>Change!</button>           </div>       )   } } export default App 

O index.css estilos index.css , index.js no arquivo index.js , contém a seguinte descrição de estilos:

 div {   display: flex;   flex-direction: column;   align-items: center;   justify-content: center; } h1 {   font-size: 3em; } button {   border: 1px solid lightgray;   background-color: transparent;   padding: 10px;   border-radius: 4px;  } button:hover {   cursor: pointer; } button:focus {   outline:0; } 

Nesse estágio, o aplicativo se parece com o mostrado na figura a seguir.


Página do aplicativo no navegador

Hoje falaremos sobre como alterar o estado dos componentes. Se o componente tem um estado, isso permite, inicializando-o, armazenar alguns dados nele. Mas se o estado não pudesse ser alterado, o componente não se beneficiaria muito de sua presença, pois armazenar os dados não seria muito diferente de, por exemplo, copiá-los no código do componente.

Vamos falar sobre o aplicativo, no exemplo do qual consideraremos trabalhar com o estado do componente. O componente App cujo código é apresentado acima é um componente baseado em classe. Isso é óbvio, pois precisamos que esse componente tenha um estado. No código do componente, usamos o construtor.

Nele, como sempre, chamamos o método super() e inicializamos o estado escrevendo a propriedade count e atribuindo a ele um valor inicial de 0 . No método render() , imprimimos um cabeçalho de primeiro nível representando o valor da propriedade count do estado do componente, bem como um botão com a palavra Change! . Tudo isso é formatado usando estilos.

Se, nesta fase do trabalho no aplicativo, abra-o em um navegador e clique no botão, é claro que nada acontecerá. Mas precisamos clicar no botão para alterar o estado do componente, afetando sua propriedade count . Ao mesmo tempo, já estudamos a metodologia de processamento de eventos no React, e nossa tarefa é criar um mecanismo que, respondendo a um clique em um botão, altere a propriedade do estado de count .

Vamos resolver o problema equipando o botão com um onClick eventos onClick , que, para iniciantes, simplesmente produzirá algo no console.

Para fazer isso, adicionaremos um novo método à classe de componentes. Você pode chamá-lo como quiser, mas é costume chamar esses métodos para que seus nomes indiquem os eventos que estão processando. Como resultado, nós, como vamos usá-lo para processar o evento click , chamamos de handleClick() . Aqui está a aparência do código do componente do App .

 import React from "react" class App extends React.Component {   constructor() {       super()       this.state = {           count: 0       }   }     handleClick() {       console.log("I'm working!")   }     render() {       return (           <div>               <h1>{this.state.count}</h1>               <button onClick={this.handleClick}>Change!</button>           </div>       )   } } export default App 

Observe que, referindo-se a esse método a partir de render() , usamos uma construção do formulário this.handleClick .

Agora, se você clicar no botão, a mensagem correspondente aparecerá no console.


Clicar no botão chama o método de classe.

Agora vamos fazê-lo para que clicar no botão aumente o número exibido acima, ou seja, modifique o estado do componente. Talvez tente alterar o estado do componente diretamente, no método handleClick() ? Digamos que se reescrevemos esse método assim:

 handleClick() {   this.state.count++ } 

Devo dizer imediatamente que isso não funciona com o estado dos componentes no React. Tentar executar esse código gerará um erro.

A condição do componente pode ser comparada com as roupas que uma pessoa veste. Se ele quer trocar de roupa, ele não altera ou repinta a roupa sem tirar a roupa, mas a tira e coloca outra coisa. Por uma questão de fato, é exatamente assim que eles trabalham com o estado dos componentes.

Você deve se lembrar de que estávamos falando de um método especial usado para modificar o estado, disponível em componentes baseados em classes devido ao fato de eles estenderem a classe React.Component . Este é o método setState() . É usado nos casos em que você precisa alterar o estado de um componente. Este método pode ser usado de diferentes maneiras.

Lembre-se de que um estado é um objeto. Vamos tentar passar para o método setState() um objeto que substituirá o estado. handleClick() o método handleClick() :

 handleClick() {   this.setState({ count: 1 }) } 

Tentar usar esse método causará o seguinte erro: TypeError: Cannot read property 'setState' of undefined . De fato, o que estamos falando agora causa muita controvérsia entre os desenvolvedores do React, e agora vou mostrar uma maneira muito simples de resolver esse problema, que, à primeira vista, pode parecer incomum.

O ponto é que, sempre que, criando um método de classe ( handleClick() no nosso caso), no qual está planejado usar o método setState() , esse método deve estar associado a this . Isso é feito no construtor. O código do componente após esta modificação terá a seguinte aparência:

 import React from "react" class App extends React.Component {   constructor() {       super()       this.state = {           count: 0       }       this.handleClick = this.handleClick.bind(this)   }     handleClick() {       this.setState({ count: 1 })   }     render() {       return (           <div>               <h1>{this.state.count}</h1>               <button onClick={this.handleClick}>Change!</button>           </div>       )   } } export default App 

Agora, depois de clicar no botão Change! o número 1 aparecerá acima, as mensagens de erro não serão exibidas.


Pressionar um botão modifica o estado

É verdade que o botão acabou sendo "único". Após o primeiro clique, 0 muda para 1 e, se você clicar novamente, nada acontecerá. Em geral, isso não é surpreendente. O código chamado quando o botão é clicado faz seu trabalho, cada vez que muda o estado para um novo, no entanto, após o primeiro clique no botão, o novo estado, no qual o número 1 é armazenado na propriedade count , não difere do antigo. Para resolver esse problema, considere outra maneira de trabalhar com o método setState() .

Se não estivermos interessados ​​no que era o estado anterior do componente, podemos simplesmente passar um objeto para esse método, que substituirá o estado. Mas muitas vezes acontece que o novo estado de um componente depende do antigo. No nosso caso, isso significa que, com base no valor da propriedade count , que é armazenada na versão anterior do estado, queremos adicionar 1 a esse valor. Nos casos em que alterar o estado, você precisa estar ciente do que foi armazenado anteriormente nele, é possível transmitir ao método setState() uma função que, como parâmetro, recebe a versão anterior do estado. Você pode nomear esse parâmetro como quiser, no nosso caso, será prevState . A aquisição desta função terá a seguinte aparência:

 handleClick() {   this.setState(prevState => {             }) } 

Você pode pensar que, em tal função, basta referir-se ao estado usando uma construção da forma this.state , mas essa abordagem não nos convém. Portanto, é importante que essa função aceite a versão anterior do estado do componente.

A função deve retornar uma nova versão do estado. Aqui está a handleClick() método handleClick() para handleClick() esse problema:

 handleClick() {   this.setState(prevState => {       return {           count: prevState.count + 1       }   }) } 

Observe que, para obter o novo valor da propriedade count , usamos a construção count: prevState.count + 1 . Você pode pensar que uma construção da count: prevState.count++ formulários count: prevState.count++ , mas o operador ++ count: prevState.count++ variável à qual é aplicada, isso significa uma tentativa de modificar a versão anterior do estado, portanto, não a usamos aqui.

O código completo do arquivo do componente nesta fase será semelhante a este:

 import React from "react" class App extends React.Component {   constructor() {       super()       this.state = {           count: 0       }       this.handleClick = this.handleClick.bind(this)   }     handleClick() {       this.setState(prevState => {           return {               count: prevState.count + 1           }       })   }       render() {       return (           <div>               <h1>{this.state.count}</h1>               <button onClick={this.handleClick}>Change!</button>           </div>       )   } } export default App 

Agora, cada clique no botão aumenta o valor do contador.


Cada clique no botão aumenta o valor do contador.

O que acabamos de descobrir abre grandes oportunidades para nós no desenvolvimento de aplicativos React.

Dissemos anteriormente que um componente pai pode, através de um mecanismo de propriedade, passar propriedades de seu próprio estado para componentes filhos. Se o React detectar uma alteração no estado do componente pai, ele renderizará novamente o componente filho para o qual esse estado é passado. Parece uma chamada para o método render() . Como resultado, o componente filho refletirá os novos dados armazenados no estado do componente pai.

Sumário


Hoje você preparou o aplicativo Todo para mais trabalhos sobre ele e também se familiarizou com os mecanismos usados ​​no React para alterar o estado de um componente. Da próxima vez, você será solicitado a expandir os recursos do aplicativo de treinamento usando o que aprendeu hoje.

Caros leitores! Como você se sente sobre o fato de que o estado dos componentes no React não pode ser alterado diretamente sem o uso de mecanismos especiais?

Source: https://habr.com/ru/post/pt439984/


All Articles