React и ES6 - Часть 4, Миксины React использующие ES6
React

React и ES6 - Часть 4, Миксины React использующие ES6

Оригинал: React and ES6 - Part 4, React Mixins when using ES6 and React, Egor Smirnov

Это четвертая часть из серии статей, рассказывающая об использовании React c ECMAScript 6 and ECMAScript 7.

Другие части вы можете найти по ссылкам:

При использовании React.createClass() у вас есть возможность использовать так называемые миксины. Они позволяют добавлять некоторую функциональность в ваши компоненты React. Эта концепция не оригинальна, она также используется в Vanilla JS и других языках / фреймворках.

Механизм миксинов нельзя использовать в компонентах, написанных на ES6. Я не буду углублятьcя в причины этого решения (множество статей было написано до меня). Если вы заинтересуетесь, вы можете получить больше информации по ссылкам ниже:

Вместо этого, мы сконцентрируемся на конкретных примерах.

Компоненты высшего порядка вместо миксинов

Мы будем работать с компонентом CartItem из второй части серии. Вы можете взять его код здесь.

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

Чтобы лучше проиллюстрировать подход, мы не будем менять код компонента CartItem. Вместо этого, мы создадим некий компонент, который будет оборачивать CartItem и «расширять» его функциональностью. Такие компоненты называются компонентами высшего порядка.

Это может звучать загадочно, но все прояснится, когда мы двинемся дальше.

P.S. Под «расширением» я имел в виду простое оборачивание компонента функцией.

Давайте рассмотрим компонент IntervalEnhance:


import React from 'react';
import { IntervalEnhance } from "./intervalEnhance";

class CartItem extends React.Component {
    // component code here
}

export default IntervalEnhance(CartItem);

Пришло время написать компонент IntervalEnhance. Добавьте новый файл intervalEnhance.jsx:


import React from 'react';

export var IntervalEnhance = ComposedComponent => class extends React.Component {

    static displayName = 'ComponentEnhancedWithIntervalHOC';

    constructor(props) {
        super(props);
        this.state = {
            seconds: 0
        };
    }

    componentDidMount() {
        this.interval = setInterval(this.tick.bind(this), 1000);
    }

    componentWillUnmount() {
        clearInterval(this.interval);
    }

    tick() {
        this.setState({
            seconds: this.state.seconds + 1000
        });
    }

    render() {
        return <ComposedComponent {...this.props} {...this.state} />;
    }
};

Некоторые объяснения.

Строка 3. Часть ComposedComponent => class extends React.Component — это то же самое, что определение функции, возвращающей класс. ComposedComponent — это компонент, который мы хотим расширить (в нашем случае CartItem). Используя export var IntervalEnhance мы даем возможность импортировать всю функцию как IntervalEnhance (в коде CartItem выше).

Строка 5. Полезна для отладки. Компонент будет называться ComponentEnhancedWithIntervalHOC в React DevTools.

Строки 7-12. Мы инициализируем состояние компонента.

Строки 14-26. Обработчики жизненного цикла компонента, которые будут запускать и останавливать счетчик для компонента.

Строка 29. Самое инетерсное здесь. Эта строка передает все свойства и состояние обертки в компонент CartItem. Благодаря этому мы можем получить доступ к this.state.seconds в компоненте CartItem.

Последний шаг — изменить метод render компонента CartItem. Мы выведем this.state.seconds в шаблоне.


import React from 'react';
import { IntervalEnhance } from "./intervalEnhance";

class CartItem extends React.Component {
    // component code here
    
    render() {
        return <article className="row large-4">
                <!-- some other tags here -->
                <p className="large-12 column">
                    <strong>Time elapsed for interval: </strong>
                    {this.props.seconds} ms
                </p>    
            </article>;
        }
}
export default IntervalEnhance(CartItem);

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

Заметьте — мы все сделали, не изменяя компонент CartItem (за исключением метода render)! Именно поэтому компоненты высшего порядка являются такими мощными.

Использование декораторов ES7 вместо миксинов

Если вам больше нравятся декораторы ES7, их можно использовать похожим способом. Например так:


import React from 'react';
import { IntervalEnhance } from "./intervalEnhance";

@IntervalEnhance
export default class CartItem extends React.Component {
    // component code here
}

Что с PureRenderMixin?

Если вы используете миксины, такие как PureRenderMixin, то существуют различные подходы добавить их функциональность в компоненты React, написанные на ES6. Один из них следующий:


class Foo extends React.Component {
   constructor(props) {
     super(props);
     this.shouldComponentUpdate = React.addons.PureRenderMixin.shouldComponentUpdate.bind(this);
   }
   render () {
     return <div>Helllo</div>
   }
}

Заключение

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

Одним из таких примеров является фреймворк Relay. Это фреймворк, основанный на React и разработанный в Facebook. Каждый компонент может быть обернут в контейнер Relay для автоматического поиска зависимостей (и многого другого). Это действительно удобно и на первый взгляд кажется магией.

Для дополнительного чтения

Рассылка
Подпишитесь на рассылку и получайте дайджест новостей и статей.
Никакого спама!
Подписаться