Вернуться

Учебный курс по React, часть 13: компоненты, основанные на классах


 Сегодня мы публикуем перевод очередного занятия учебного курса по React. Оно посвящено компонентам, основанным на классах. Такие компоненты создают с использованием ключевого слова class.

Учебный курс по React, часть 12: практикум, третий этап работы над TODO-приложением

→ Часть 1: обзор курса, причины популярности React, ReactDOM и JSX
→ Часть 2: функциональные компоненты
→ Часть 3: файлы компонентов, структура проектов
→ Часть 4: родительские и дочерние компоненты
→ Часть 5: начало работы над TODO-приложением, основы стилизации
→ Часть 6: о некоторых особенностях курса, JSX и JavaScript
→ Часть 7: встроенные стили
→ Часть 8: продолжение работы над TODO-приложением, знакомство со свойствами компонентов
→ Часть 9: свойства компонентов
→ Часть 10: практикум по работе со свойствами компонентов и стилизации
→ Часть 11: динамическое формирование разметки и метод массивов map
→ Часть 12: практикум, третий этап работы над TODO-приложением

Занятие 24. Компоненты, основанные на классах

Если вы, до того, как начали осваивать этот учебный курс, изучали React по материалам каких-то других курсов, у вас может возникнуть вопрос по поводу того, что здесь мы пользуемся функциональными компонентами. Дело в том, что во многих других курсах эта тема либо не освещается, либо о функциональных компонентах говорят как о чём-то таком, в чём нет особой необходимости. Некоторые авторы идут ещё дальше и говорят о том, что функциональные компоненты лучше не использовать, отдавая предпочтение компонентам, основанным на классах. Это, по их мнению, избавляет программиста от ненужной нагрузки. Я же полагаю, что любому, кто изучает React, полезно будет увидеть полную картину и узнать о популярных в наши дни подходах по работе с компонентами. В частности, сейчас актуально направление, в соответствии с которым везде, где это возможно, используют функциональные компоненты, а компоненты, основанные на классах — лишь там, где они действительно необходимы. При этом надо отметить, что всё это — лишь рекомендации. Каждый разработчик сам решает как именно он будет конструировать свои приложения.

Когда я веду курсы по React, я предпочитаю начинать с функциональных компонентов, так как функции — понятные конструкции. Одного взгляда на функциональный компонент достаточно для того, чтобы понять, какие именно действия он выполняет. Скажем, вот код функционального компонента, который представляет собой обычную функцию, возвращающую элемент <div>, содержащий элемент <h1> с неким текстом.

function App() {
    return (
        <div>
            <h1>Code goes here</h1>
        </div>
    )
}

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

Преобразуем функциональный компонент в компонент, основанный на классе. Если вы не особенно хорошо знакомы с ключевым словом class, появившемся в ES6, и с возможностями, которые оно открывает перед разработчиками, рекомендуется уделить некоторое время на то, чтобы познакомиться с классами поближе.

Описание компонента, основанного на классах, начинается с ключевого слова class. Затем идёт имя компонента, составляемое по тем же правилам, что и имена функциональных компонентов. При этом после конструкции наподобие class App будет идти не нечто вроде фигурной скобки, а конструкция вида extends React.Component. После неё ставится пара фигурных скобок, в которых будет описано тело класса.

Классы в JavaScript представляют собой надстройку над традиционной моделью прототипного наследования. Сущность конструкции class App extends React.Component сводится к тому, что мы объявляем новый класс и указываем на то, что его прототипом должен быть React.Component. Наличие у нашего компонента этого прототипа позволяет пользоваться в этом компоненте всеми теми полезными возможностями, которые имеются в React.Component.

Итак, на данном этапе работы над компонентом, основанном на классах, его код выглядит так:

class App extends React.Component {
    
}

У компонента, основанного на классах, должен быть, по меньшей мере, один метод. Это — метод render(). Данный метод должен возвращать то же самое, что мы обычно возвращаем из функциональных компонентов. Вот как выглядит полный код компонента, основанного на классах, реализующего те же возможности, что и вышеприведённый функциональный компонент.

class App extends React.Component {
    render() {
        return (
            <div>
                <h1>Code goes here</h1>
            </div>
        )
    }
}

Работают с компонентами, основанными на классах так же, как с функциональными компонентами. То есть, в нашем случае достаточно заменить код функционального компонента на новый код и приложение будет работать так же, как и прежде.

Поговорим о методе render(). Если, перед формированием элементов, возвращаемых этим методом, нужно выполнить некие вычисления, их выполняют именно в этом методе, перед командой return. То есть, если у вас есть некий код, определяющий порядок формирования визуального представления компонента, этот код нужно поместить в метод render. Например, тут можно выполнить настройку стилей в том случае, если вы пользуетесь встроенными стилями. Здесь же будет и код, реализующий механизм условного рендеринга, и другие подобные конструкции. 
Если вы знакомы с классами, вы можете создать собственный метод и разместить код, готовящий компонент к визуализации, в нём, после чего вызвать этот метод в методе render. Выглядит это так:

class App extends React.Component {
    
    yourMethodHere() {
        
    }
    
    render() {
        const style = this.yourMethodHere()
        return (
            <div>
                <h1>Code goes here</h1>
            </div>
        )
    }
}

А именно, тут мы исходим из предположения о том, что в методе yourMethodHere() производится формирование стилей, а то, что он возвращает, записывается в константу style, объявленную в методе render(). Обратите внимание на то, что для обращения к нашему собственному методу используется ключевое слово this. Позже мы поговорим об особенностях этого ключевого слова, но пока остановимся на представленной здесь конструкции.

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

При использовании функциональных компонентов мы объявляли соответствующую функцию с параметром props, представляющим собой объект, в который попадало то, что передавалось компоненту при создании его экземпляра. Выглядит это так:

function App(props) {
    return (
        <div>
            <h1>{props.whatever}</h1>
        </div>
    )
}

При работе с компонентом, основанном на классе, то же самое выглядит так:

class App extends React.Component {
    render() {
        return (
            <div>
                <h1>{this.props.whatever}</h1>
            </div>
        )
    }
}

Итоги

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

16 февраля 2019 г. 14:14

Если вам понравилась эта статья поделитесь ею с друзьями, тем самым вы помогаете нам развиваться и добавлять всё больше интересного и полезного контента!