Частые трудности работы с React.js
Не паникуйте. Вы правы: существуют мириады веб-технологий, архитектур и фреймворков, и множество разрабатывается прямо сейчас. Помните: каждый, кто стал профессиональным веб-разработчиком начинал как и вы. Они изучали языки, библиотеки по одному, раз за разом, пока не прокачали свои навыки и механизмы работы
Веб-разработка сейчас как первый поход в супермаркет. На прилавках сотни товаров, которыми хочется овладеть. Растерявшись, очень легко испугаться огромному выбору. Ошибкой будет пытаться изучить все сразу, будто бы вам нужно везде быть компетентным.
На самом деле, если вы сконцентрируетесь на одной вещи, например на создании сайта на простейшем HTML/CSS/JavaScript без библиотек, а потом добавите фреймворк по типу React’а, ваш путь от новичка до профессионала пройдет гораздо удобнее и приятнее.
1 — Название компонента со строчной буквы
Компонент React должен иметь имя, начинающееся с заглавной буквы. Если это не так, то компонент будет обработан как встроенный: div или span.
Попытайтесь передать фреймворку (отрендерить) <greeting /> — React выдаст ошибку:
Что и говорит нам: “Начинайте с заглавной буквы, сложно что ли?”.
*И никогда не называйте компонент button, img и другими тегами. React просто проигнорирует их и отрендерит как голый HTML-тег.*
2 — Использование одиночных кавычек вместо обратных апострофов
Строки создаются обратными апострофами (`. `) (ориг. “Back-ticks”), и они отличаются от обычных одиночных кавычек (‘. ’).
На большинстве клавиатур обратные апострофы можно поставить, нажав на клавишу выше Tab.
Именно их мы используем, когда нам нужно вставить в строку динамичное выражение, не используя разрыв строки и последующую конкатенацию.
Давайте представим ситуацию: нужно вывести сообщение о том, сколько сейчас времени “Время: …”
Также, внутри обратных апострофов можно делать перенос строки.
С обычными одинарными кавычками вы такого не провернете.
3 — Использование React.PropTypes
Объект PropTypes был удален из React’а. Его просто нет, и нужно привыкнуть. Зато теперь:
- Добавляем новый модуль prop-types: npm install prop-types
- Импортируем в нужный файл: import PropTypes from ‘prop-types’
Если до сих пор в коде есть строчка с React.PropTypes, то вы получите ошибкой по голове:
4 — Использование версий, описанных в туториале
Когда просматриваете или прочитываете уроки программирования и следуете примерам оттуда, убедитесь, что у вас установлена соответствующая уроку версия. Обычно применение последних версий модулей безопасно, но туториал бывает устаревшим. Вследствие вы обязательно столкнетесь с ошибками. И наоборот, если в туториале используется React 16, не поленитесь заменить вашу 15-ую версию.
Особенно это бывает важно для Node.js. Ошибки со старыми версиями там на каждом углу. Например, в Node 7.x убрали Object.values, так что проще будет обновиться, чем исправлять свой код на Node 6.x
5 — Путаница между функциями и классами
Сможете ли вы сказать, где ошибка в этом коде?
Код неверен, потому что внутри тела JavaScript класса у вас нет прав практически ни на что. Вы лишь можете объявлять методы и свойства через ограниченный синтаксис.
Это и правда запутывает, потому что фигурные скобки в синтаксе класса выглядят как привычная блочная структура, но это не так.
Если хотите свободы в действиях, применяйте компоненты, основанные на функциях:
6 — Числа как строки
Вы можете передать свойства с помощью строки:
Если нужно передать число, то НЕ пишите их в кавычках:
Вместо этого вставьте их в фигурные скобки:
Используя внутри компонента Greeting, вы сможете достать ваше число с помощью this.props.counter и можно совершенно безопасно проводить с ним математические операции. Случай неправильного применения “7” может привести к непредсказуемым последствиям.
7 — Два приложения на одном порте
Чтобы запустить веб-сервер, вам нужен хост (например 127.0.0.1) и порт (например 8080), чтобы заставить сервер прослушивать запросы по правильному http-адресу.
Как только сервер запустится, он имеет полный контроль над портом. Вам больше не удастся включить на этот же порт ваш утюг. Он будет занят (Порт, а не утюг!).
Попробуйте запустить тот же сервер из другого терминала. Скорее всего вы получите ошибку “Используется”:
Иногда получается, что порт используется в фоновом режиме. Вы его не видите, но он мешает жить. В таких ситуациях бывает выгодно необходимо “убить” тот, который занимает драгоценный порт:
8 — Переменные окружения
Некоторые проекты зависят от существования переменных окружения (ориг. “Environmental variables”). Если запустить приложение без необходимых переменных, то оно попробует запуститься, используя значения undefined (не определено), и, конечно же, это приведет к критическим ошибкам.
К примеру, если проект подключен к базе данных MongoDB, то переменные окружения типа process.env.Mongo_URI пригодятся, чтобы безопасно подключаться к базе. Также их можно быстро менять в зависимости от обстановки (мало ли нужно подключить другую БД).
Чтобы запустить проект с MongoDB локально, сначала нужно экспортировать переменную MONGO_URI. Обязательно, если база работает, скажем, на порте 27017, сделайте это до того, как запускать приложение:
9 — Фигурные или круглые () скобки
Первый пример попробует (и у него не получится) вернуть объект, в то время как второй сумеет вызвать функцию something() и вернуть то, что функция должна вернуть.
С тех пор как <тег> в синтаксисе JSX будет вызывать функцию, эта проблема применима к любому JSX коду.
Также она применима к стрелочным функциям (ориг. “Arrow functions”). Вместо
*Просто запомните: в ES6 фигурные скобки для стрелочных функций не нужны!*
10 — Необорачивание объектов в круглые скобки
Закончим тему из предыдущего пункта. Нетрудно запутаться, обращаясь к стрелочным функциям для того же, чтобы вернуть обычный объект.
Без оборачивания объекта в круглые скобки, у вас никогда не получится добиться того, ради чего был придуман короткий синтаксис.
Для закрепления рассмотрим похожий готовый пример:
11 — Использование неправильной буквы в методах
React.Component, a не React.component. componentDidMount, а не ComponentDidMount. Вообще-то ReactDOM, но не ReactDom.
Обращайте внимание на то, как написаны различные методы, потому что, допустив такую ошибку, можно провозиться с ней реально много времени, а потом будет за себя стыдно. Попробуйте ESLint, он поможет отследить такие ошибки.
Часто ошибки возникают при обращении к свойствам:
Например, если вместо props.userName вписать props.username или props.UserName, то вернется значение undefined.
12 — Ошибки в применении объекта состояния
В компонентах-классах можно объявить локальный объект state, а позже получить его значение через this:
Программа выведет “Привет, Мир” .
Вместо state можно использовать любое название объекта. Например:
Выведет то же самое.
Однако разница есть. state — особый объект, которым управляет React. Вы можете изменить значение через setState и React отреагирует на это. Такой трюк не пройдет с примером кода выше, хотя вы все же можете его использовать, если не желаете видеть реакцию.
13 — Каша в <тег/> и </тег>
Не забывайте ставить прямой слеш /, когда закрываете тег. И да, иногда вам понадобиться <тег/>, а иногда </тег>.
В HTML есть самозакрывающиеся теги (ориг. “self-closing tag”). Это элементы без “детей”. К примеру img относится к таким:
В тег div можно вложить сколько угодно других, поэтому надо как открывать, так и закрывать его:
Это же правило применимо к компонентам React.
Однако, если у него нет “детей”, вы все равно можете открывать/закрывать его, а также можно использовать самозакрывающийся тег:
Пример неверного применения:
От того вы должны увидеть ошибку:
14 — Ожидание, что import/export “просто заработают”
Возможность import/export официально поддерживается JavaScript с 2015 года. Тем не менее, это единственное из ES2015, что не в полной форме поддерживается всеми браузерами и самой поздней версией Node.
Часто проекты на React создают с Webpack и Babel. Они позволяют компилировать ваш код в то, что будут понимать все браузеры. Поэтому использовать import/export лучше вместе с Webpack и Babel.
Чтобы заставить Node понимать import/export, а это иногда нужно, например в тех случаях, когда вы используете их на фронте (frontend) и имеете SSR (Server-Side Rendering — рендеринг на сервере, изоморфное приложение). Для этого вам понадобится присутствие Babel’я на самом Node. Для удобства разработки советую подключить что-то из pm2, nodemon, babel-watch.
15 — Проблемы с Bind
Вы можете объявить методы класса в компонентах React, а затем включать их в метод render. К примеру: Я использовал метод whoIsThis внутри render’a с помощью this.whoIsThis, потому что именно в таком случае this обращается к элементу DOM (то есть к самому компоненту).
React пытается убедиться в этом. Однако, JavaScript даже не старается автоматически связать (ориг. “bind”) this и метод whoIsThis.
Протестируем это на примерах. Строка console.dir в whoIsThis выведет объект Greeting, потому что метод был вызван прямо из render’а:
Однако, когда вы используете метод класса в том месте, которое будет вызвано не сразу, например в обработчике событий (ориг. “Event handler”), то console.dir не выведет того, что ожидалось:
В примере выше React вызывает метод whoIsThis только после нажатия на строку, что не даст вам доступа к компоненту изнутри. Именно поэтому вы получите undefined.
Это предисловие о том, что часто проблема возникает, когда из метода класса пытаются получить this.props или this.state. Просто не будет работать. Для решения существует много способов. Можно обернуть метод в функцию или использовать .bind, чтобы заставить метод запоминать того, кто его вызывает. Также можно делать bind в конструкторе класса, а не в render’е.
Все же лучшим решением будет использование возможностей из ECMAScript (это stage-3) для классов через Babel, а в обработчиках писать стрелочные функции: