Convertendo React.createClass para React.Component
No meu último artigo falei sobre como corrigir versões mais antigas do React para funcionar em um ambiente moderno. Neste artigo vou mais longe e dou um guia passo a passo para atualizar um componente React clássico para um moderno, mudando a React.createClass
maneira de fazer as coisas para o método moderno e preferido React.Component
.
Os arquivos que precisamos estarão nas pastas ‘Original’ e ‘Final’ do diretório de componentes na solução GitHub que acompanha.
Obter arquivos de tutorial do GitHub
Novamente trabalhando com o componente [react-checkbox-list](https://github.com/sonyan/react-checkbox-list)
da Sony An (disponível como react-checkbox-list
em npm ). Este guia mostra passo a passo como substituir a estrutura e os métodos de um React.createClass
componente clássico por um moderno React.Component
.
Começando com o .jsx
arquivo na react-checkbox-list
solução, primeiro vamos excluir o .js
arquivo e renomeá-lo, .js
pois os .jsx
arquivos não precisam mais ser nomeados de forma diferente.
Isso nos dá o seguinte código inicial:
Convertendo o componente
Ao tentar carregar este código, o primeiro erro que recebemos éUncaught Error: Module build failed: SyntaxError: The @jsx React.DOM pragma has been deprecated as of React 0.12
Erro não capturado: Falha na compilação do módulo: SyntaxError: O pragma @jsx React.DOM foi preterido a partir do React 0.12
É simples o suficiente para corrigir isso. Basta remover a linha /** @jsx React.DOM */
da parte superior do documento.
Agora temos Uncaught TypeError: Cannot read property 'array' of undefined
o mesmo erro do tutorial de patch. Isso ocorre porque o React.propTypes foi preterido na versão 15.50 do React, então de acordo com esse tutorial, vá em frente e instale o pacote PropTypes com o comando via npm. Vamos importar isso para o nosso pacote mais tarde.[React.createClass](https://wholesomecode.ltd/blog/broken-react-createclass-component-lets-fix-it/)
npm install --save prop-types
O que se segue agora é uma revisão completa da base de código, então não podemos atualizar e corrigir um erro como fizemos anteriormente, então não saberemos se funcionou até o final. Preparar-se!
Vamos começar substituindo a React.createClass
função declarando um novo React.Component
. Altere nosso código para que fique assim:
'use strict';
import React from 'react';
class CheckBoxList extends React.Component {
...
}
Observe que fizemos algumas coisas aqui:
- Removido o comentário JSX de abertura
- Alterado o tipo de declaração
var React =...
paraimport React from 'react';
este é a maneira moderna de fazer declarações no React. - Agora declaramos uma nova classe de
CheckBoxList
, em vez de exportar uma função. - Devido à sintaxe do objeto agora estar entre parênteses
{...}
, precisamos descartar o fechamento);
No entanto, esta nova classe agora está faltando uma maneira de exportá-la para que outros componentes possam usá-la, então vamos adicionar uma declaração de exportação na parte inferior desse código.
'use strict';
import React from 'react';
class CheckBoxList extends React.Component {
...
}
export default CheckBoxList;
Em nosso código original, a primeira linha de código na função era displayName: 'CheckBoxList',
nossa exportação agora lida com isso, para que possamos remover esse código completamente.
A próxima linha declara propTypes
que estes agora estão fora da classe e precisam da PropTypes
dependência que adicionamos via npm. Vamos adicionar isso em nossas importações e escrever os PropTypes assim:
'use strict';
import React from 'react';
import PropTypes from 'prop-types';
class CheckBoxList extends React.Component {
...
}
CheckBoxList.propTypes = {
defaultData: PropTypes.array,
onChange: PropTypes.func,
};
export default CheckBoxList;
Em seguida, o estado é declarado através do método getInitialState
com React.Component
que definimos nosso estado inicial com um construtor. Adicione o seguinte código em nossa compilação:
...
class CheckBoxList extends React.Component {
constructor( props) {
super( props );
this.state = {
data: [],
}
}
...
}
...
Lá vamos nós, que configura o estado do componente, mas espere, nós ainda não dissemos a ele de onde obter seu estado. É aí que componentWillMount
vem a calhar.
...
class CheckBoxList extends React.Component {
constructor( props) {
super( props );
this.state = {
data: [],
}
}
componentWillMount() {
this.setState({
data: this.props.defaultData,
});
}
...
}
...
Uma coisa importante a ser observada é que os métodos internos de React.Component
não terminam em vírgulas (,
), portanto, certifique-se de que quaisquer métodos adicionados ao componente não terminem em vírgula!
Em seguida, vamos adicionar a função de renderização de volta. Esta é provavelmente a parte mais fácil, é quase a mesma coisa, com a diferença chave que mudamos render: function() {
para apenas render() {
.
Para fins de manter este tutorial direto ao ponto, não converterei os dois métodos reset
e, checkAll
no entanto, os conceitos usados para a porta do método handleItemChange
apple para ambos, portanto, sinta-se à vontade para experimentá-los.
Para migrar o handleItemChange
método, primeiro precisamos remover a vírgula de fechamento (,
) e alterar o tipo de declaração da função handleItemChange: function(e) {
para handleItemChange( e) {
garantir que ainda passemos e
como parâmetro do evento.
Vamos adicionar isso acima do nosso método de renderização.
...
class CheckBoxList extends React.Component {
...
handleItemChange( e) {
var selectedValues = [],
newData = [];
this.state.data.forEach(function(item) {
if(item.value == e.target.value) {
item.checked = e.target.checked;
}
if(item.checked) {
selectedValues.push(item.value);
}
newData.push(item);
});
this.setState( {data: newData} );
if(this.props.onChange) {
this.props.onChange(selectedValues);
}
}
...
}
...
Nosso componente agora será renderizado, porém não será funcional. Ao tentar clicar em uma caixa de seleção, você receberá o erro Uncaught TypeError: Cannot read property 'state' of undefined
.
Erro de tipo não capturado: não é possível ler a propriedade ‘estado’ de indefinido
Isso porque em nosso handleItemChange
método, onde tentamos acessar o estado, this
é indefinido. Para corrigir isso, precisamos vincular nossa função this
adicionando a seguinte linha em nosso construtor: this.handleItemChange = this.handleItemChange.bind( this );
.
...
class CheckBoxList extends React.Component {
constructor( props) {
super( props );
this.state = {
data: [],
}
this.handleItemChange = this.handleItemChange.bind( this );
}
...
}
...
E aí está, nosso recém-convertido componente React em ação.
React.createClass para React.Component
Código-fonte do tutorial
Você pode baixar o código-fonte da versão original e final do componente no GitHub. O plugin contém um bloco WordPress Gutenberg que você pode usar para brincar com o código, com três arquivos que você pode excluir conforme aplicável:
Os arquivos de tutorial do GitHub para a conversão de React.createClass para React.Component