Как добавить ReactJS в существующее веб-приложение
Очень часто при ознакомлении с новой технологией, будь то JavaScript фреймворк или методология CSS, мы сталкиваемся с простым вызовом: “А как добавить эту крутую вещь на свой старый и запущенный сайт?” Многие руководства показывают, как это сделать с чистого листа, но в реальности у нас далеко не всегда есть такая роскошь.
В этой статье я дам несколько базовых примеров по использованию ReactJS в качестве замены для существующего кода, написанного на jQuery.
От jQuery к React
Недавно передо мной была поставлена задача взять достаточно большой функционал, написанный на jQuery и переписать его на React. Процесс был очень сложным, так как jQuery был распылен по разным местам кодовой базы. Построение полного пользовательского интерфейса с jQuery вполне возможно (и мы делаем это уже многие годы), но при этом возникают сложности с масштабируемостью и поддерживаемостью.
Независимо от того, что вы используете — Angular, Ember, Vue, React или jQuery, вы пытаетесь сделать то же, что долгие годы делали разработчики:
Вывести HTML → Получить события от пользователей → Обновить HTML
Так как jQuery сильно зависит от селекторов типа .classes и #IDs , используемых для манипуляций с DOM, HTML становится запутанным и перенасыщенным атрибутами, которые нужны лишь для того, чтобы сообщать jQuery о своем существовании. Это не представляет особой проблемы при небольшом объеме кода, но с его увеличением становится сложно расшифровать, какие классы для CSS, а какие для JavaScript. Если вам приходилось когда-либо искать селекторы .class или #ID в ваших шаблонах HTML или в JavaScript для изменения какой-нибудь функциональности, то вы понимаете, о чем я.
Архитектура с сильной зависимостью от идентификаторов и классов при выборке и манипуляции HTML может быть очень хрупкой.Так что делать, если ваш код пронизан jQuery или целиком построен на каком-нибудь ином фреймворке, как начать заменять элементы пользовательского интерфейса чем-то типа React?
На что надо сразу обратить внимание?
Обертка/элемент-контейнерНезависимо от того, используется ли в приложении jQuery или другой популярный фреймворк, в большинстве случаев будет использоваться своего рода корневой элемент, оборачивающий фрагмент пользовательского интерфейса. Если в кодовой базе для реализации функционала используется jQuery, то обычно есть элемент, действующий как селектор-обертка. Этот элемент находится с помощью используется и используется для динамического обновления DOM.
Изолированное и распределенное состояниеТакже стоит уяснить, изолировано ли состояние вашего функционала в отдельном контейнере или разделено между несколькими элементами.
- Изолированное состояние — состояние изолировано в отдельном контейнере. Любая интерактивность (все кнопки, поля ввода и т.д.) содержится внутри контейнера.
- Распределенное состояние — состояние разбросано по множественным элементам. Примером этого может быть календарь, обновляемый путем выбора даты из выпадающего меню в другом месте страницы. Меню и календарь являются раздельными контейнерами, но делят состояние и функциональность.
Я собираюсь показать четыре примера распределенного/изолированного состояния с jQuery и затем с ReactJS.
Пример изолированного состояния с jQuery
Предположим, у нас есть существующее веб-приложение, показывающее эмодзи и кнопку, при нажатии на которую выводится другой эмодзи. Ниже показан код, который является образцом типичного приложения jQuery, в нем мы находим основной родительский элемент и динамически вносим в него изменения.
Вот разметка этого примера:
Это самая распространенная, хотя и не единственная стратегия изменения DOM с помощью jQuery.
Пример изолированного состояния с ReactJS
Одним из преимуществ использования библиотеки типа React является возможность инкапсулировать JavaScript и HTML внутри компонента. Результат получается более надежным, поддерживаемым и подходящим для многократного использования.
Это особенно помогает при работе с большими приложениями, в которых рендеринг и обновление производятся совместно внутри компонента. Я имею в виду не смешивание логики и представления, а согласованную организацию JavaScript и HTML внутри компонента. Эта же идея реализуется во всех JavaScript фреймворках, отсюда и сам термин фреймворк.
Как правило, все фреймворки:
- Монтируются к определенному контейнеру (к элементу div с #id , например).
- Выводят содержимое в контейнер.
- Отслеживают и обновляют содержимое в контейнере.
- Удаляют контейнер в отдельных случаях.
Итак, наша разметка с интеграцией React:
Пример распределенного состояния с jQuery
Мы легко можем делать это с jQuery, но когда одна часть сайта динамически влияет на другую при помощи простых селекторов это сильно запутывает код. Опять-таки, при использовании классов и идентификаторов для манипуляции DOM, вы обязаны сами все это отслеживать.
В этом примере мы используем название эмодзи в селекторах .Mood__name и .Mood__button-name и обновляем эмодзи в одном контейнере с помощью кнопки из другого контейнера. Это можно немного очистить, но без особого успеха, так как пытаясь управлять всем только с помощью селекторов jQuery, мы всегда загрязняем код.
Пример распределенного состояния с React
В ReactJ есть два распространенных способа работы с состоянием, распределенным между несколькими компонентами.
- Обернуть компоненты в контейнер для управления состоянием и передать данные/функции в дочерние компоненты как свойства.
- Использование библиотек типа Redux для помещения состояния и действий на глобальный уровень и подсоединения компонентов к ним.
Это широко распространенная практика особенно для одностраничных приложений или фрагментов пользовательского интерфейса, полностью выводимых при помощи React. Так как мы хотим, чтобы наши компоненты общались друг с другом, мы оборачиваем их родительским контейнером, а он передает вниз свойства для обновления каждого компонента. Именно так работает ReactJS из коробки и в этом нет ничего нового.
Этот метод хорошо работает в тех случаях, когда у вас есть возможность обернуть пользовательский интерфейс одним контейнером. В большинстве давно поддерживаемых приложений это невозможно, но в некоторых случаях, в зависимости от раскладки пользовательского интерфейса, может быть вариантом.
Использование Redux для распределенного состоянияБиблиотеки типа Redux (и различные варианты Flux) облегчают коммуникацию между компонентами, расположенными в разных областях приложения. Это распределенное состояние позволяет вам подсоединять действия и свойства состояния к вашим компонентам путем обновления глобального объекта, предоставляемого Redux.
Заключение
Надеюсь, у вас появилось понимание того, на что нужно обращать внимание при интеграции ReactJS в существующее приложение. При использовании jQuery для фрагмента пользовательского интерфейса вы можете заменить контейнер монтируемым компонентом React. А если состояние разделено между нескольким компонентами, то вы можете использовать метод контейнера или подключить библиотеку типа Redux.