React, без сомнения, одна из самых популярных интерфейсных платформ JavaScript / библиотек пользовательского интерфейса. Однако это не значит, что это лучший или всем нравится.

Среди наиболее технических причин, по которым люди не любят React, на удивление, есть одна из самых больших его функций - JSX. Расширение стандартного JavaScript, позволяющее использовать HTML-подобный синтаксис в ваших компонентах React.

Как такую ​​узнаваемую часть React, которая явно призвана улучшить читаемость и простоту написания кода, можно превратить в мошенничество? Что ж, все сводится к разделению проблем.

Разделение проблем

Прежде чем мы углубимся, я хотел бы объяснить, что такое разделение ответственности, чтобы не упустить никаких нюансов.

Итак, разделение проблем означает наличие четких границ между различными концепциями / частями чего-либо. В программировании JSX является ярким примером игнорирования этого правила. У нас больше нет «шаблона», описывающего структуру компонента в отдельном HTML-файле и его логику в JS-файле, но оба (или подробнее, если вы используете CSS-in-JS) смешиваются вместе, чтобы сформировать то, что одни считают идеальной гармонией, а другие - неконтролируемым хаосом.

Личное предпочтение

Хорошо, смешивание «представления» и «логики» вместе приводит к нарушению разделения проблем. Но разве это плохо и означает ли это, что вы всегда должны хранить представление и логику вашего компонента отдельно?

Нет и нет. Во-первых, отсутствие разделения интересов - не обязательно плохо. Это вопрос личных предпочтений разработчика или команды и других правил. Вам не нужно хранить свою логику и рассматривать отдельно. Но если вы это сделаете, это еще не значит, что каждому из них нужен отдельный файл. Прекрасными примерами этого являются Однофайловые компоненты Vue (SFC) или просто чистый HTML-файл с тегами <script> и <style> внутри них.

Реагировать на крючки

Разделение проблем - это одно, а перехватчики React - другое.

Итак, React hooks существуют уже довольно давно (почти 2 года с стабильного релиза), поэтому они довольно хорошо известны и уже засыпаны многими другими блогами и разработчиками. Но давайте еще раз сделаем краткий обзор.

Перехватчики React позволяют разработчикам добавлять состояние и использовать другие специальные функции React внутри функциональных компонентов, в отличие от прежних требований к компонентам на основе классов. . Всего их 10 встроенных (v17.0.1), каждая для обработки различных функций React, из которых только 4 обычно используются (useState(), useEffect(), useContext() и useRef()), и вы, естественно, можете Создай свой. И это последняя часть информации, которая нас больше всего интересует.

Крючки на заказ

Хотя сами хуки React должны быть в какой-то степени хорошо известны, процесс создания собственной ловушки несколько менее вероятен.

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

Создание крючка

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

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

Честно говоря, вам даже не нужно делать ничего из этого - использование других хуков не требуется (но довольно часто), и если ваш код хорошего качества, пользовательское имя хука начинается с use, и вы используете хуки по назначению (на самом верхнем уровне компонента React), тогда все будет в порядке.

Примеры

Вот очень простой хук, который запускает предоставленный обратный вызов каждую секунду (потому что я не мог придумать ничего лучше 🙃):

… И вот как это можно использовать:

Что касается ловушки, которая зависит от другой ловушки, вот такая, которая заставляет ваш компонент обновляться без заметного изменения состояния с помощью useState() 'в фоновом режиме'.

… И вот пример использования:

В качестве примечания стоит сказать, что такое принудительное обновление обычно не следует использовать. В большинстве случаев это либо бессмысленно, либо указывает на некоторые потенциальные ошибки в вашем коде. Единственное исключение из этого правила - неуправляемые компоненты.

Предложение решения

Думаю, теперь вы понимаете, к чему все идет. Независимо от того, насколько бессмысленными были мои примеры, оба они все же имеют одно преимущество - они абстрактная логика отстранены от функции основного компонента, что в результате делает его более чистым.

Теперь остается только увеличить масштаб этой идеи, потенциально отодвинув получившуюся ловушку от самого файла компонента, и вуаля! У вас есть довольно хорошее разделение задач - в React!

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

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

Лучшие практики

Итак, если вы в конечном итоге попробуете такой подход в одном из своих проектов, то у меня есть несколько «лучших практик», которым я лично следую и которые могут вас заинтересовать:

  • применяйте эту тактику только в том случае, если логика вашего компонента занимает ›10 строк или имеет много более мелких вызовов ловушки;
  • поместите ваш хук в отдельный файл, в котором в идеале не должно быть никакого JSX (`.js` vs .jsx files);
  • сохраняйте единообразие наименования - например, перехватить logic.js или hook.js (с соответствующим именем перехватчика, например useComponentNameLogic()) и сам компонент в view.jsx или index.jsx в одной папке с дополнительным файлом index.js (если он еще не зарезервирован для компонента) для повторного экспорта необходимые биты;
  • оставьте в JSX-файле только самые простые обратные вызовы и прослушиватели событий, а остальные переместите в ловушку;
  • при использовании библиотеки CSS-in-JS, которая имеет дело с хуками (например, useStyles()), поместите ее в отдельный файл или в начало файла компонента, если он не слишком большой;
  • не забудьте правильно организовать код вашей ловушки - разделить часть ее на внешние функции и, возможно, даже на более мелкие хуки, если логика повторно используется в разных компонентах.

Что вы думаете?

Это мое предложение по реализации разделения ответственности в React. Это лучший подход, который вы должны использовать? Определенно нет, к тому же не существует вообще никакого "наилучшего подхода". Опять же, я только что обнаружил, что это соответствует моим потребностям, и я хотел поделиться им с вами в надежде, что это может помочь и вам.

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

Как всегда, чтобы получать больше подобного контента, не забудьте подписаться на меня в Twitter, Facebook или через мою рассылку новостей. Спасибо за чтение и удачного кодирования!