✅ Новости WEB и WordPress, темы, плагины. Здесь мы делимся советами и лучшими решениями для веб-сайтов.

Преобразование React.createClass в React.Component

29

В своей прошлой статье я рассказывал о патчинге старых версий React для работы в современной среде. В этой статье я пойду еще дальше и дам пошаговое руководство по обновлению классического компонента React до современного, заменив React.createClassспособ ведения дел на современный и предпочтительный React.Componentметод.

Нужные нам файлы будут находиться в папках «Исходный» и «Конечный» каталога компонентов в сопутствующем решении GitHub.

Получить учебные файлы с GitHub

Снова работа с компонентом [react-checkbox-list](https://github.com/sonyan/react-checkbox-list) Sony An (доступен как react-checkbox-listна npm ). В этом руководстве шаг за шагом показано, как заменить структуру и методы классического React.createClassкомпонента на современный React.Component.

Начиная с .jsxфайла в react-checkbox-listрешении, мы сначала удалим .jsфайл и переименуем его, .jsтак как .jsxфайлы больше не нужно называть по-другому.

Это дает нам следующий стартовый код:


'use strict';
var React = require('react');

module.exports = React.createClass({
    displayName: 'CheckBoxList',

    propTypes: {
        defaultData: React.PropTypes.array,
        onChange: React.PropTypes.func
    },

    getInitialState: function() {
        return {
            data: this.props.defaultData || []
        };
    },

    handleItemChange: function(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);
        }
    },

    reset: function() {
        var newData = [];
        this.state.data.forEach(function(item) {
            item.checked = false;
            newData.push(item);
        });

        this.setState({data: newData});
    },

    checkAll: function() {
        var newData = [];
        this.state.data.forEach(function(item) {
            item.checked = true;
            newData.push(item);
        });

        this.setState({data: newData});
    },

    render: function() {
        var options;

        options = this.state.data.map(function(item, index) {
            return (<div key={'chk-' + index} className="checkbox">
                    <label>
                        <input
                            type="checkbox"
                            value={item.value}
                            onChange={this.handleItemChange}
                            checked={item.checked? true: false} /> {item.label}
                    </label>
                </div>
            );
        }.bind(this));

        return (<div>
                {options}
            </div>
        );
    }
});

Преобразование компонента

При попытке загрузить этот код первая ошибка, которую мы получаем,Uncaught Error: Module build failed: SyntaxError: The @jsx React.DOM pragma has been deprecated as of React 0.12

Uncaught Error: сбой сборки модуля: SyntaxError: прагма @jsx React.DOM устарела, начиная с React 0.12

Исправить это достаточно просто. Просто удалите строку /** @jsx React.DOM */из верхней части документа.

Теперь мы получаем ту Uncaught TypeError: Cannot read property 'array' of undefinedже ошибку, что и в учебнике по исправлению. Это связано с тем, что React.propTypes устарел в версии React 15.50, поэтому, согласно этому руководству, установите пакет PropTypes с помощью команды через npm. Мы импортируем это в наш пакет позже.[React.createClass](https://wholesomecode.ltd/blog/broken-react-createclass-component-lets-fix-it/)

npm install --save prop-types

Далее следует полная переработка кодовой базы, поэтому мы не можем обновить и исправить ошибку, как мы могли сделать ранее, поэтому мы не узнаем, сработало ли это до самого конца. Пристегнитесь!

Давайте начнем с замены React.createClassфункции, объявив новый React.Component. Измените наш код, чтобы он выглядел следующим образом:

'use strict';
import React from 'react';

class CheckBoxList extends React.Component {
...
}

Обратите внимание, что мы сделали здесь несколько вещей:

  • Удален начальный комментарий JSX.
  • Изменен тип объявления с var React =...на import React from 'react';это современный способ создания объявлений в React.
  • Теперь мы объявляем новый класс CheckBoxListвместо экспорта функции.
  • Из-за синтаксиса объекта, который теперь заключен в круглые скобки {...}, нам нужно удалить закрывающий);

Однако в этом новом классе теперь отсутствует способ экспорта, чтобы другие компоненты могли его использовать, поэтому давайте добавим объявление экспорта внизу этого кода.

'use strict';
import React from 'react';

class CheckBoxList extends React.Component {
...
}

export default CheckBoxList;

В нашем исходном коде первой строкой кода в функции был displayName: 'CheckBoxList',наш экспорт, который теперь обрабатывает это, поэтому мы можем полностью удалить этот код.

Следующая строка объявляет, что propTypesтеперь они находятся вне класса и нуждаются в PropTypesзависимости, которую мы добавили через npm. Давайте добавим это в наш импорт и напишем PropTypes так:

'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;

Затем состояние объявляется с помощью метода, getInitialStateи React.Componentмы устанавливаем наше начальное состояние с помощью конструктора. Добавьте в нашу сборку следующий код:

...
class CheckBoxList extends React.Component {
    constructor( props) {
        super( props );
        this.state = {
            data: [],
        }
    }
...
}
...

Вот и все, это устанавливает состояние компонента, но подождите, мы на самом деле не сказали ему, откуда взять его состояние. Вот где componentWillMountпригодится.

...
class CheckBoxList extends React.Component {
    constructor( props) {
        super( props );
        this.state = {
            data: [],
        }
    }

    componentWillMount() {
        this.setState({
            data: this.props.defaultData,
        });
    }
...
}
...

Важно отметить, что внутренние методы React.Componentне заканчиваются запятыми (,), поэтому убедитесь, что любые методы, которые вы добавляете к компоненту, не заканчиваются запятой!

Далее, давайте добавим обратно функцию рендеринга. Это, наверное, самая простая часть, она почти такая же, с той ключевой разницей, что мы render: function() {просто меняем на render() {.

...
class CheckBoxList extends React.Component {
...
    render() {
        var options;

        options = this.state.data.map(function(item, index) {
            return (<div key={'chk-' + index} className="checkbox">
                    <label>
                        <input
                            type="checkbox"
                            value={item.value}
                            onChange={this.handleItemChange}
                            checked={item.checked? true: false} /> {item.label}
                    </label>
                </div>
            );
        }.bind(this));

        return (<div>
                {options}
            </div>
        );
    }
...
}
...

В целях сохранения актуальности этого руководства я не буду преобразовывать два метода resetи, checkAllтем не менее, концепции, используемые для порта метода handleItemChangeApple, в оба, поэтому не стесняйтесь попробовать их самостоятельно.

Чтобы перенести handleItemChangeметод, нам сначала нужно удалить закрывающую запятую (,) и изменить тип объявления функции с handleItemChange: function(e) {на handleItemChange( e) {убедившись, что мы по-прежнему передаем eего в качестве параметра события.

Давайте добавим это выше нашего метода рендеринга.

...
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);
        }
    }
...
}
...

Теперь наш компонент будет отображаться, но не будет работать. Когда вы попытаетесь нажать на флажок, вы получите сообщение об ошибке Uncaught TypeError: Cannot read property 'state' of undefined.

Uncaught TypeError: невозможно прочитать состояние свойства неопределенного

Это потому, что в нашем handleItemChangeметоде, где мы пытаемся получить доступ к состоянию, thisоно не определено. Чтобы исправить это, нам нужно привязать нашу функцию к this, добавив следующую строку в наш конструктор: this.handleItemChange = this.handleItemChange.bind( this );.

...
class CheckBoxList extends React.Component {
    constructor( props) {
        super( props );
        this.state = {
            data: [],
        }
        this.handleItemChange = this.handleItemChange.bind( this );
    }
...
}
...

И вот он, наш недавно преобразованный компонент React в действии.

Преобразование React.createClass в React.ComponentReact.createClass для React.Component

Исходный код учебника

Вы можете скачать исходный код оригинальной и финальной версии компонента на GitHub. Плагин содержит блок WordPress Gutenberg, который вы можете использовать для экспериментов с кодом, с тремя файлами, которые вы можете удалить, если это применимо:

Преобразование React.createClass в React.ComponentУчебные файлы GitHub для преобразования React.createClass в React.Component

Источник записи: wholesomecode.ltd

Этот веб-сайт использует файлы cookie для улучшения вашего опыта. Мы предполагаем, что вы согласны с этим, но вы можете отказаться, если хотите. Принимаю Подробнее