Konvertera React.createClass till React.Component
I min förra artikel pratade jag om att patcha äldre versioner av React för att fungera i en modern miljö. I den här artikeln går jag ett steg längre och ger en steg-för-steg-guide för att uppgradera en klassisk React-komponent till en modern, genom att byta ut React.createClass
sättet att göra saker på till den moderna och föredragna React.Component
metoden.
Filerna vi behöver finns i mapparna ‘Original’ och ‘Slutlig’ i komponentkatalogen i den medföljande GitHub-lösningen.
Få handledningsfiler från GitHub
Återigen arbetar med komponenten [react-checkbox-list](https://github.com/sonyan/react-checkbox-list)
från Sony An (tillgänglig react-checkbox-list
från npm ). Denna guide visar dig steg för steg hur du byter ut strukturen och metoderna för en klassisk React.createClass
komponent till en modern React.Component
.
Från och med .jsx
filen i react-checkbox-list
lösningen kommer vi först att ta bort .js
filen och byta namn på den till .js
eftersom .jsx
filer inte längre behöver heta annorlunda.
Det ger oss följande startkod:
Konvertera komponenten
När vi försöker ladda den här koden är det första felet vi fårUncaught Error: Module build failed: SyntaxError: The @jsx React.DOM pragma has been deprecated as of React 0.12
Ofångat fel: Modulbygget misslyckades: SyntaxError: @jsx React.DOM-pragman har fasats ut från och med React 0.12
Det är enkelt att rätta till detta. Ta bara bort raden /** @jsx React.DOM */
från toppen av dokumentet.
Vi får nu samma fel som Uncaught TypeError: Cannot read property 'array' of undefined
i patchhandledningen [React.createClass](https://wholesomecode.ltd/blog/broken-react-createclass-component-lets-fix-it/)
. Detta beror på att React.propTypes fasades ut i React version 15.50, så enligt den handledningen, fortsätt och installera PropTypes-paketet med kommandot via npm. Vi kommer att importera detta till vårt paket senare.
npm install --save prop-types
Det som följer nu är en fullständig översyn av kodbasen, så vi kan inte uppdatera och fixa ett fel som vi kan ha gjort tidigare, så vi kommer inte att veta om det har fungerat förrän i slutet. Spänn fast!
Låt oss börja med att ersätta React.createClass
funktionen genom att deklarera en ny React.Component
. Ändra vår kod så att den ser ut så här:
'use strict';
import React from 'react';
class CheckBoxList extends React.Component {
...
}
Observera att vi har gjort några saker här:
- Tog bort den inledande JSX-kommentaren
- Ändrad deklarationstyp från
var React =...
tillimport React from 'react';
detta är det moderna sättet att göra deklarationer i React. - Vi deklarerar nu en ny klass av
CheckBoxList
istället för att exportera en funktion. - På grund av syntaxen för objektet som nu är innesluten inom parentes
{...}
måste vi ta bort stängningen);
Men den här nya klassen saknar nu ett sätt att exportera den så att andra komponenter kan använda den, så låt oss lägga till en exportdeklaration längst ner i den koden.
'use strict';
import React from 'react';
class CheckBoxList extends React.Component {
...
}
export default CheckBoxList;
I vår ursprungliga kod hanterar den första kodraden i funktionen var displayName: 'CheckBoxList',
vår export nu detta, så vi kan ta bort den koden helt.
Nästa rad ner förklarar att propTypes
dessa nu sitter utanför klassen och behöver det PropTypes
beroende som vi lagt till via npm. Låt oss lägga till det i våra importer och skriva PropTypes så här:
'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;
Därefter deklareras tillståndet via metoden getInitialState
där React.Component
vi ställer in vårt initiala tillstånd med en konstruktor. Lägg till följande kod i vårt bygge:
...
class CheckBoxList extends React.Component {
constructor( props) {
super( props );
this.state = {
data: [],
}
}
...
}
...
Där går vi, som ställer in komponentens tillstånd, men håll ut, vi har faktiskt inte berättat för den var den ska få sitt tillstånd ifrån. Det är där som componentWillMount
kommer väl till pass.
...
class CheckBoxList extends React.Component {
constructor( props) {
super( props );
this.state = {
data: [],
}
}
componentWillMount() {
this.setState({
data: this.props.defaultData,
});
}
...
}
...
En viktig sak att notera är att de inre metoderna för React.Component
inte slutar med kommatecken (,
), så se till att alla metoder du lägger till i komponenten inte slutar med komma!
Nästa upp, låt oss lägga till renderingsfunktionen igen. Detta är förmodligen den enklaste delen, den är nästan densamma, med nyckelskillnaden att vi ändrar render: function() {
till bara render() {
.
För att hålla den här handledningen till punkten kommer jag inte att konvertera de två metoderna reset
och checkAll
hur begreppen som används för porten av handleItemChange
metodäpplet till båda, så försök gärna med dem själv.
För att migrera handleItemChange
metoden måste vi först ta bort det avslutande kommatecken (,
) och ändra funktionsdeklarationstypen från handleItemChange: function(e) {
att handleItemChange( e) {
se till att vi fortfarande skickar e
in som händelseparameter.
Låt oss lägga till det ovanför vår renderingsmetod.
...
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);
}
}
...
}
...
Vår komponent kommer nu att renderas, men den kommer inte att fungera. När du försöker klicka på en kryssruta får du felet Uncaught TypeError: Cannot read property 'state' of undefined
.
Uncaught TypeError: Kan inte läsa egenskapen "state" för odefinierad
Detta beror på att i vår handleItemChange
metod, där vi försöker komma åt staten, this
är odefinierad. För att fixa detta måste vi binda vår funktion till this
genom att lägga till följande rad i vår konstruktor: this.handleItemChange = this.handleItemChange.bind( this );
.
...
class CheckBoxList extends React.Component {
constructor( props) {
super( props );
this.state = {
data: [],
}
this.handleItemChange = this.handleItemChange.bind( this );
}
...
}
...
Och där har vi det, vår nykonverterade React-komponent i aktion.
React.createClass till React.Component
Handlednings källkod
Du kan ladda ner källkoden för den ursprungliga och slutliga versionen av komponenten på GitHub. Pluginet innehåller ett WordPress Gutenberg-block som du kan använda för att leka med koden, med tre filer som du kan ta bort i förekommande fall:
GitHub Tutorial-filer för React.createClass till React.Component-konverteringen