Conversión de React.createClass a React.Component
En mi último artículo hablé sobre parchear versiones anteriores de React para que funcionen en un entorno moderno. En este artículo voy más allá y doy una guía paso a paso para actualizar un componente React clásico a uno moderno, cambiando la React.createClass
forma de hacer las cosas al React.Component
método moderno y preferido.
Los archivos que necesitamos estarán en las carpetas ‘Original’ y ‘Final’ del directorio de componentes en la solución GitHub adjunta.
Obtener archivos de tutoriales de GitHub
Nuevamente trabajando con el componente [react-checkbox-list](https://github.com/sonyan/react-checkbox-list)
de Sony An (disponible react-checkbox-list
en npm ). Esta guía le muestra paso a paso cómo reemplazar la estructura y los métodos de un React.createClass
componente clásico a uno moderno React.Component
.
Comenzando con el .jsx
archivo en la react-checkbox-list
solución, primero eliminaremos el .js
archivo y cambiaremos su nombre para .js
que los .jsx
archivos ya no necesiten tener un nombre diferente.
Eso nos da el siguiente código de inicio:
Convertir el componente
Al intentar cargar este código, el primer error que obtenemos esUncaught Error: Module build failed: SyntaxError: The @jsx React.DOM pragma has been deprecated as of React 0.12
Error no detectado: Falló la construcción del módulo: SyntaxError: el pragma @jsx React.DOM ha quedado obsoleto a partir de React 0.12
Es bastante simple corregir esto. Simplemente elimine la línea /** @jsx React.DOM */
de la parte superior del documento.
Ahora obtenemos el mismo error Uncaught TypeError: Cannot read property 'array' of undefined
que en el tutorial de aplicación de parches. Esto se debe a que React.propTypes quedó obsoleto en la versión 15.50 de React, así que según ese tutorial, continúe e instale el paquete PropTypes con el comando a través de npm. Importaremos esto en nuestro paquete más tarde.[React.createClass](https://wholesomecode.ltd/blog/broken-react-createclass-component-lets-fix-it/)
npm install --save prop-types
Lo que sigue ahora es una revisión completa del código base, por lo que no podemos actualizar y corregir un error como lo hicimos anteriormente, por lo que no sabremos si funcionó hasta el final. ¡Cinturón de seguridad!
Comencemos reemplazando la React.createClass
función declarando un nuevo React.Component
. Modifique nuestro código para que se vea como lo siguiente:
'use strict';
import React from 'react';
class CheckBoxList extends React.Component {
...
}
Tenga en cuenta que hemos hecho algunas cosas aquí:
- Se eliminó el comentario JSX de apertura.
- Alteró el tipo de declaración de
var React =...
aimport React from 'react';
esta es la forma moderna de hacer declaraciones en React. - Ahora declaramos una nueva clase de
CheckBoxList
, en lugar de exportar una función. - Debido a que la sintaxis del objeto ahora está encerrado entre paréntesis
{...}
, debemos eliminar el cierre);
Sin embargo, a esta nueva clase ahora le falta una forma de exportarla para que otros componentes puedan usarla, así que agreguemos una declaración de exportación en la parte inferior de ese código.
'use strict';
import React from 'react';
class CheckBoxList extends React.Component {
...
}
export default CheckBoxList;
En nuestro código original, la primera línea de código en la función era displayName: 'CheckBoxList',
nuestra exportación ahora maneja esto, por lo que podemos eliminar ese código por completo.
La siguiente línea hacia abajo declara que propTypes
estos ahora se encuentran fuera de la clase y necesitan la PropTypes
dependencia que agregamos a través de npm. Agreguemos eso a nuestras importaciones y escribamos los PropTypes así:
'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;
A continuación, el estado se declara a través del método getInitialState
con el React.Component
que establecemos nuestro estado inicial con un constructor. Agregue el siguiente código en nuestra compilación:
...
class CheckBoxList extends React.Component {
constructor( props) {
super( props );
this.state = {
data: [],
}
}
...
}
...
Ahí vamos, eso establece el estado del componente, pero espera, en realidad no le hemos dicho de dónde obtener su estado. Ahí es donde componentWillMount
viene bien.
...
class CheckBoxList extends React.Component {
constructor( props) {
super( props );
this.state = {
data: [],
}
}
componentWillMount() {
this.setState({
data: this.props.defaultData,
});
}
...
}
...
Una cosa clave a tener en cuenta es que los métodos internos de React.Component
no terminan en comas (,
), ¡así que asegúrese de que cualquier método que agregue al componente no termine en coma!
A continuación, volvamos a agregar la función de renderizado. Esta es probablemente la parte más fácil, es casi lo mismo, con la diferencia clave de que cambiamos render: function() {
a solo render() {
.
Con el fin de mantener este tutorial al grano, no convertiré los dos métodos reset
y, checkAll
sin embargo, los conceptos utilizados para el puerto del método handleItemChange
apple a ambos, así que no dude en intentarlos usted mismo.
Para migrar el handleItemChange
método, primero debemos eliminar la coma de cierre (,
) y modificar el tipo de declaración de la función handleItemChange: function(e) {
para handleItemChange( e) {
asegurarnos de que aún lo pasemos e
como el parámetro del evento.
Agreguemos eso arriba de nuestro método de renderizado.
...
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);
}
}
...
}
...
Nuestro componente ahora se renderizará, sin embargo, no será funcional. Cuando intente hacer clic en una casilla de verificación, obtendrá el error Uncaught TypeError: Cannot read property 'state' of undefined
.
TypeError no capturado: no se puede leer la propiedad ‘estado’ de indefinido
Esto se debe a que en nuestro handleItemChange
método, donde intentamos acceder al estado, this
no está definido. Para solucionar esto, debemos vincular nuestra función this
agregando la siguiente línea en nuestro constructor: this.handleItemChange = this.handleItemChange.bind( this );
.
...
class CheckBoxList extends React.Component {
constructor( props) {
super( props );
this.state = {
data: [],
}
this.handleItemChange = this.handleItemChange.bind( this );
}
...
}
...
Y ahí lo tenemos, nuestro componente React recién convertido en acción.
React.createClass a React.Component
Código fuente del tutorial
Puede descargar el código fuente de la versión original y final del componente en GitHub. El complemento contiene un bloque de WordPress Gutenberg que puede usar para jugar con el código, con tres archivos que puede eliminar según corresponda:
Los archivos de tutorial de GitHub para la conversión de React.createClass a React.Component