React практически не добавляет к нативному JS внешней абстракции. Поэтому разработчику необходимо хорошо разбираться в основах языка.
В этой статье разберем самые нужные для React концепции JavaScript.
Вхождение в React
Первое что мы видим после создания проекта с create-react-app – это классы компонентов:
Здесь много концепций, которые не связаны с фреймворком напрямую: ключевое слово class, наследование, методы, интерполяция, импорт и экспорт. Кажется, без понимания нативного JavaScript в React делать нечего. Начнем с самых простых вещей и увидим, что в React больше JS, чем мы думали.
Стрелочные функции
Стрелочные функции – одно из недавних приобретений JavaScript. Они делают код намного короче и проще.
Строковые литералы
Мы привыкли к такому синтаксису конкатенации строк в JS:
А шаблоны строк позволяют использовать интерполяцию с помощью обратных кавычек и нотации $<> :
Их можно использовать также для реализации многострочности:
Компоненты
React и JS-классы
Классы появились в языке относительно недавно, заменив собой цепочки прототипов. Один из способов определения компонентов в React основан именно на них.
Оператор new вызывает конструктор класса, который создает новый объект, обладающий некоторыми свойствами и методами.
Оператор extends позволяет одному классу наследовать от другого. Класс-наследник может расширять функциональность родителя собственными методами.
Все компоненты React наследуют об базового класса Component , импортированного из пакета React.
Метод render является обязательным, так как класс Component вызывает его для отображения чего-либо в браузере. Без расширения базового компонента не получится использовать методы жизненного цикла, например, componentDidMount , а также метод setState , управляющий локальным состоянием.
Таким образом, использование JS-классов позволяет расширить существующий функционал базового компонента и получить доступ к API React.
Сокращенный синтаксис
Если компонент имеет собственные методы, их необходимо привязать в конструкторе. Там же создается объект состояния:
Если таких компонентов много, то привязка методов и вообще создание конструктора становится весьма утомительной задачей. К счастью, существует сокращенный синтаксис:
Использование стрелочных функций JavaScript позволяет не биндить методы. А если конструктор не использует props , его вообще можно убрать, определив состояние непосредственно как свойство класса. (Свойства класса еще не входят в стандарт JS.)
Компоненты-функции
Некоторые компоненты должны получать входные данные и просто возвращать отображаемые HTML-элементы без управления состоянием. Такие компоненты называются функциональными, они менее сложны и более удобны.
Для их создания можно использовать стрелочные функции JS.
Выражения импорта и экспорта
Любой create-react-app проект начинается с инструкций import и export:
Переменные, компоненты или функции, объявленные в одном файле:
можно импортировать в другой:
Весь экспорт можно получить в виде единого объекта:
Чтобы избежать совпадений имен при импорте используются псевдонимы.
Есть также вариант импорта/экспорта по умолчанию. Он используется, если экспортируется всего одна переменная или если требуется выделить главную функциональность модуля.
Импортировать дефолтный объект можно без фигурных скобок и с другим именем.
Можно сочетать дефолтный и именованный экспорт:
Это основные функции ES6 модулей. Они помогают организовать код, удобно поддерживать его, тестировать и повторно использовать.
JavaScript detected
Деструктуризация и spread-оператор
Если требуется получить доступ к большому количеству свойств из state или props , можно использовать новую возможность JavaScript – деструктуризацию.
Входящий параметр можно деструктурировать прямо в сигнатуре функции.
Для сохранения незадействованных при деструктурировании свойств объекта существует параметр rest .
С его помощью можно передать неиспользованные данные дальше по цепочке компонентов, используя spread-оператор.
Map, Reduce и Filter
Вывести в JSX-коде одну переменную или свойство объекта нетрудно, нужно просто обернуть их в фигурные скобки. Но как вывести список? В React не существует какого-то специального API или атрибута для рендеринга коллекции элементов, нужно использовать нативные возможности языка.
Можно еще сократить код, используя стрелочные функции:
JS-метод map просто проходит по массиву и возвращает JSX-код для каждого элемента. Иногда вместо map следует применять filter или reduce .
Тернарный оператор
В JSX нельзя напрямую использовать конструкцию if. else , но можно воспользоваться тернарным оператором JS:
Функции высшего порядка
Рассмотрим пример фильтрации списка пользователей на основе значения поля ввода.
Выделим фильтрующую функцию из компонента, чтобы было удобнее ее тестировать и передадим в метод filter как параметр.
Но doFilter ничего не знает о свойстве query . Чтобы все заработало, мы превратим ее в функцию высшего порядка.
Стрелочные функции сделают запись более краткой.
Теперь doFilter можно экспортировать из файла и тестировать изолированно от компонента.
Поняв этот принцип, вы без труда разберетесь в React-компонентах высшего порядка.
Больше JavaScript, чем React
Фреймворк React имеет тонкую прослойку аутентичного API, но все остальное – это чистый JavaScript. Давайте убедимся в этом, отрефакторив компонент высшего порядка, а заодно повторим изученное.
Это компонент-обертка для отображения индикатора загрузки. Вы уже можете видеть деструктурирование и работу spread-оператора, который позволяет передать все неиспользованные свойства из объекта props.
Первым шагом рефакторинга будет превращение компонента в функциональный:
Переносим деструктуризацию в сигнатуру параметра и используем стрелочную функцию для краткости:
Добавим тернарный оператор:
Очевидно, что методы, которые использует компонент высшего порядка, принадлежат не фреймворку, а языку. Таким образом, React-приложения базируются на возможностях JS. Расширить их функциональность можно с помощью различных внешних библиотек.