O livro Reage Rápido. Aplicações Web em React, JSX, Redux e GraphQL »

imagem Oi, habrozhiteli! A edição original foi lançada no outono de 2017, mas ainda é considerado o melhor livro para explorar o React. O autor está constantemente atualizando e modificando o código do livro no repositório do Github .

Em um post, sugerimos que você se familiarize com a passagem "Estados e seu papel na natureza interativa do React"

Se você tivesse que ler apenas um capítulo deste livro, deveria escolher este! Sem estados, os componentes do React permanecem apenas em padrões estáticos avançados. Espero que você compartilhe meu entusiasmo, porque a compreensão dos conceitos deste capítulo permitirá que você construa aplicativos muito mais interessantes.


Imagine que você está construindo um campo de entrada com preenchimento automático (Fig. 4.1). Ao inserir dados, o campo deve emitir uma solicitação ao servidor para obter informações sobre as opções adequadas para exibir a saída em uma página da web. Você trabalhou com propriedades até agora e sabe que alterar propriedades permite obter visualizações diferentes. No entanto, as propriedades não podem ser alteradas no contexto do componente atual, porque são transmitidas quando o componente é criado.

imagem Em outras palavras, as propriedades são imutáveis ​​no componente atual, o que significa que você não pode alterar as propriedades desse componente, a menos que recrie o componente e transfira novos valores do pai (Fig. 4.2). Mas as informações recebidas do servidor precisam ser armazenadas em algum lugar e, em seguida, uma nova lista de opções deve ser exibida na exibição. Como atualizar a exibição se as propriedades não podem ser alteradas?

Uma solução possível é renderizar um elemento com novas propriedades sempre que você receber uma nova resposta do servidor. Mas então você deve colocar a lógica fora do componente - e o componente deixa de ser auto-suficiente. Obviamente, se os valores das propriedades não puderem ser alterados e o preenchimento automático for auto-suficiente, é impossível usar propriedades. Em seguida, surge a pergunta: como atualizar visualizações em resposta a eventos sem recriar o componente (createElement () ou JSX <NAME />)? É esse problema que os estados resolvem.

imagem

Depois que a resposta do servidor estiver pronta, o código de retorno de chamada mudará o estado do componente de acordo. Você terá que escrever esse código você mesmo. No entanto, após a atualização do estado, o React atualizará automaticamente a visualização para você (apenas nos locais em que deve ser atualizado, ou seja, onde os dados do estado são usados).

Com o estado dos componentes do React, é possível criar aplicativos React interativos e significativos. Estado é um conceito fundamental que permite criar componentes do React que podem armazenar dados e atualizar automaticamente as visualizações de acordo com as alterações nos dados.

Qual é o estado do componente React?


O estado React é um armazenamento de dados de componente mutável - blocos orientados a função independentes da interface e lógica do usuário. "Variabilidade" significa que os valores dos estados podem mudar. Usando o estado na vista (render ()) e alterando os valores posteriormente, você pode influenciar a aparência da vista.

Metáfora: se você imaginar um componente como uma função, para a entrada de quais propriedades e estado são transferidos, o resultado da função será uma descrição da interface do usuário (apresentação). Propriedades e estados expandem as visualizações, mas são usadas para diferentes propósitos (consulte a seção 4.3).

Ao trabalhar com estados, você os acessa pelo nome. O nome é um atributo (ou seja, uma chave de objeto ou uma propriedade de objeto - não uma propriedade de componente) deste objeto state.state, por exemplo this.state.autocompleMatches ou this.state.inputFieldValue.

Os dados de estado geralmente são usados ​​para exibir informações dinâmicas em uma exibição para estender a renderização de exibições. Retornando a um exemplo anterior de um campo de preenchimento automático: o estado muda em resposta a uma solicitação XHR para o servidor, que, por sua vez, é iniciado inserindo dados no campo. React garante que as visualizações sejam atualizadas quando o estado usado nas visualizações for alterado. De fato, quando um estado muda, apenas as partes correspondentes das representações mudam (para elementos individuais e até mesmo os valores de atributo de um elemento individual).

Tudo o resto no DOM permanece inalterado. Isso é possível graças ao modelo DOM virtual (consulte a seção 1.1.1), que o React usa para determinar o delta (totalidade das alterações) durante o processo de reconciliação. Esse fato permite escrever código em um estilo declarativo. React faz toda a rotina para você. Os principais estágios da alteração da apresentação são discutidos no Capítulo 5.

Os desenvolvedores de reação usam estados para gerar novas interfaces de usuário. As propriedades do componente (this.props), variáveis ​​comuns (inputValue) e atributos de classe (this.inputValue) não são adequadas para isso, porque a alteração de seus valores (no contexto do componente atual) não inicia uma alteração na exibição. Por exemplo, o seguinte snippet é antipadrão, o que mostra que alterar o valor em qualquer lugar, exceto no estado, não fará com que a exibição seja atualizada:

// :   ! let inputValue = 'Texas' class Autocomplete extends React.Component { updateValues() ← {      ( ) this.props.inputValue = 'California' inputValue = 'California' this.inputValue = 'California' } render() { return ( <div> {this.props.inputValue} {inputValue} {this.inputValue} </div> ) } } 

Agora vamos ver como trabalhar com os estados dos componentes do React.

Trabalhar com estados


Para trabalhar com estados, você deve poder acessar valores, atualizá-los e definir valores iniciais. Vamos começar consultando os estados nos componentes React.

Acesso aos estados


O objeto de estado é um atributo do componente e você deve acessá-lo através deste link, por exemplo, this.state.name. Como você se lembra, as variáveis ​​podem ser acessadas e exibidas no código JSX entre chaves ({}). Da mesma forma, em render (), você pode renderizar this.state (como qualquer outra variável ou atributo de classe de um componente não padrão), por exemplo {this.state.inputFieldValue}. Essa sintaxe é semelhante à sintaxe para acessar propriedades em this.props.name.

imagem Usamos o que você aprendeu para implementar o relógio na fig. 4.3 Nosso objetivo é criar uma classe de componente autônoma que qualquer pessoa possa importar e usar em seu aplicativo sem muito aborrecimento. O relógio deve exibir a hora atual.

O projeto tem a seguinte estrutura:

 /clock index.html /jsx script.jsx clock.jsx /js script.js clock.js react.js react-dom.js 

Eu uso a CLI Babel com sinalizadores de rastreamento (-w) e diretório (-d) para compilar todos os arquivos de origem JSX de clock / jsx para a pasta clock / js de destino e recompilar quando alterações são detectadas. Além disso, salvei o comando como um script npm no arquivo package.json da pasta pai ch04 para executar o comando npm run build-clock a partir de ch04:

 "scripts": { "build-clock": "./node_modules/.bin/babel clock/jsx -d clock/js -w" }, 

Obviamente, o tempo não pára (gostemos ou não). Por esse motivo, você precisa atualizar constantemente a exibição e, para isso, pode usar o estado. Nomeie-o como currentTime e tente renderizar o estado, como mostra a Listagem 4.1.

Listagem 4.1. Renderização de estado JSX

 class Clock extends React.Component { render() { return <div>{this.state.currentTime}</div> } } ReactDOM.render( <Clock />, document.getElementById('content') ) 

Você receberá uma mensagem de erro: TypeError não capturado: Não é possível ler a propriedade 'currentTime' de null. Normalmente, as mensagens de erro do JavaScript têm os mesmos benefícios que um copo de água fria para uma pessoa que está se afogando. É bom que, pelo menos nesse caso, o JavaScript exiba uma mensagem significativa.

A mensagem indica que o valor de currentTime é indefinido. Diferentemente das propriedades, os estados não são definidos no pai. Chamar setState em render () também falha, porque criará um loop (setState -> render -> setState ...) - e o React reportará um erro.

Atribuição do estado inicial


Você já viu que antes de usar os dados do estado em render (), você deve inicializar o estado. Para definir o estado inicial, use this.state no construtor com a sintaxe da classe ES6 React.Component. Lembre-se de chamar super () com propriedades; caso contrário, a lógica no pai (React.Component) não funcionará:

 class MyFancyComponent extends React.Component { constructor(props) { super(props) this.state = {...} } render() { ... } } 

Ao atribuir o estado inicial, você também pode adicionar outra lógica - por exemplo, defina o valor de currentTime usando a nova Data (). Você também pode usar toLocaleString () para obter o formato de data / hora correto para o local atual do usuário, conforme mostrado abaixo (ch04 / relógio).

Listagem 4.2. Construtor do componente Clock

 class Clock extends React.Component { constructor(props) { super(props) this.state = {currentTime: (new Date()).toLocaleString()} } ... } 

O valor this.state deve ser um objeto. Não entraremos em detalhes do constructor () do ES6; consulte o Apêndice D e o Resumo do ES6 em github.com/azat-co/cheatsheets/tree/master/es6 . A linha inferior é que, como em outras linguagens OOP, um construtor (ou seja, construtor ()) é chamado quando uma instância da classe é criada. O nome do método construtor deve ser exatamente isso; considere esta uma das regras do ES6. Além disso, ao criar o método constructor (), a chamada super () quase sempre deve ser incluída nele, sem a qual o construtor do pai não seria executado. Por outro lado, se você não definir o método constructor (), a chamada para super () será assumida por padrão.

O nome currentTime é opcional; você deve usar o mesmo nome posteriormente ao ler e atualizar esse estado.

O objeto de estado pode conter objetos ou matrizes aninhados. O exemplo a seguir adiciona uma matriz de descrições de livros ao estado:

 class Content extends React.Component { constructor(props) { super(props) this.state = { githubName: 'azat-co', books: [ 'pro express.js', 'practical node.js', 'rapid prototyping with js' ] } } render() { ... } } 

O método constructor () é chamado apenas uma vez, ao criar um elemento React com base na classe. Portanto, você pode definir o estado diretamente usando this.state apenas uma vez - no método constructor (). Não configure ou atualize o estado diretamente com this.state = ... em outro lugar, pois isso pode levar a conseqüências imprevistas.

Então você obtém apenas o valor inicial, que rapidamente se tornará obsoleto - em apenas 1 segundo. Quem precisa de um relógio que não mostre a hora atual? Felizmente, existe um mecanismo para atualizar o estado atual.

Atualização de status


O estado é alterado pelo método da classe this.setState (data, callback). Quando esse método é chamado, o React combina os dados com os estados atuais e chama render (), após o qual chama retorno de chamada.

Definir um retorno de chamada em setState () é importante porque o método funciona de forma assíncrona. Se o aplicativo depender do novo estado, você poderá usar esse retorno de chamada para garantir que o novo estado esteja disponível.

Se você simplesmente presumir que o estado foi atualizado sem aguardar a conclusão de setState (), ou seja, trabalhar de forma síncrona ao executar uma operação assíncrona, poderá ocorrer um erro: o programa depende da atualização dos valores do estado, mas o estado permanece antigo.
Até agora, geramos tempo do estado. Você já sabe como definir o estado inicial, mas deve ser atualizado a cada segundo, certo? Para fazer isso, use a função de timer do navegador setInterval () (http://mng.bz/P2d6), que atualizará o estado a cada n milissegundos. O método setInterval () é implementado em quase todos os navegadores modernos como global, o que significa que pode ser usado sem bibliotecas ou prefixos adicionais. Um exemplo:

 setInterval(()=>{ console.log('Updating time...') this.setState({ currentTime: (new Date()).toLocaleString() }) }, 1000) 

Para iniciar a contagem regressiva, você precisa chamar setInterval () apenas uma vez. Criamos o método launchClock () exclusivamente para esse fim; launchClock () será chamado no construtor. A versão final do componente é mostrada na Listagem 4.3 (ch04 / clock / jsx / clock.jsx).

imagem

O método setState () pode ser chamado em qualquer lugar, não apenas no método launchClock () (que é chamado no construtor), como no exemplo. Normalmente, o método setState () é chamado de um manipulador de eventos ou como um retorno de chamada quando os dados são recebidos ou atualizados.

DICA Uma tentativa de alterar o estado no código com um comando no formato this.state.name = 'novo nome' não levará a nada. Não levará à renderização e atualização do modelo DOM real, do que você gostaria. Na maioria dos casos, uma alteração direta de estado sem setState () é antipadrão e deve ser evitada.

É importante observar que o método setState () atualiza apenas os estados que foram passados ​​para ele (parcialmente ou mesclados, mas sem uma substituição completa). Ele não substitui o objeto de estado inteiro toda vez. Portanto, se apenas um dos três estados for alterado, os outros dois permanecerão inalterados. No exemplo a seguir, userEmail e userId não serão alterados:

 constructor(props) { super(props) this.state = { userName: 'Azat Mardan', userEmail: 'hi@azat.co', userId: 3967 } } updateValues() { this.setState({userName: 'Azat'}) } 

Se você pretende atualizar todos os três estados, precisará fazer isso explicitamente passando os novos valores desses estados para setState (). (Também no código antigo, que agora não funciona mais, o método this.replaceState () às vezes é encontrado; é oficialmente descontinuado1. Como você pode imaginar pelo nome, substituiu todo o objeto de estado por todos os seus atributos.

Lembre-se de que chamar setState () inicia a execução de render (). Na maioria dos casos, funciona. Em alguns casos especiais em que o código depende de dados externos, você pode iniciar uma nova renderização chamando this.forceUpdate (). No entanto, essas decisões são indesejáveis, porque depender de dados externos (em vez de estado) torna os componentes menos confiáveis ​​e dependentes de fatores externos (ligação restrita).

Como mencionado anteriormente, o objeto state pode ser acessado na entrada this.state. No JSX, os valores de saída são colocados entre chaves ({}), portanto, para declarar uma propriedade state em uma visualização (ou seja, no comando de retorno do método render), use a notação {this.state.NAME}.

A magia de reação ocorre quando você usa dados de estado em uma exibição (por exemplo, na saída, em um comando if / else, como um valor de atributo ou valor de propriedade de um filho) e depois passa novos valores para setState (). Bah! O React atualiza toda a marcação HTML necessária para você. Você pode verificar isso no console do DevTools, onde os ciclos "Atualizando ..." e "Renderizando ..." devem ser exibidos. E o melhor é que isso afetará apenas os elementos DOM mínimos absolutos necessários.

»Mais informações sobre o livro podem ser encontradas no site do editor
» Conteúdo
» Trecho

Cupom de desconto de 20% para vendedores ambulantes - reagir

Após o pagamento da versão em papel do livro, uma versão eletrônica do livro é enviada por e-mail.

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


All Articles