После моей статьи об интуитивно понятном, свободном от шаблонов решении глобального состояния для React я решил положить в основу концепции реальные данные. Я начал с простого примера приложения React, которое использует Redux для глобального управления состоянием, и преобразовал его в ReactN. В ходе этого процесса я измерил объективные изменения в распределении памяти и размере пакета. Тщательный анализ и исходный код предоставлены на GitHub, но я подведу итоги здесь, а также покажу, насколько легко выполняется преобразование и насколько проще становится отредактированный код.
Вы можете использовать ReactN самостоятельно через reactn on NPM или вносить свой вклад, форк или иным образом следить за репозиторием GitHub с открытым исходным кодом.
Приложение 0️⃣
Приложение представляет собой демонстрацию функций глобального состояния. При монтировании приложение извлекает страницу и сохраняет ответ в глобальном состоянии. При рендеринге кнопка отображает число из глобального состояния. Когда кнопка нажата, число увеличивается.
Это не потрясающая функциональность. Это демонстрация трех наиболее важных аспектов глобального состояния: способность читать из него, возможность писать в него и способность управлять им асинхронно.
Создание глобального состояния в React состоит из четырех частей, и мы рассмотрим каждую из них: зависимости, инициализация глобального состояния, подключение компонентов к состоянию, а также чтение и запись в глобальное состояние.
Приложение Redux 1️⃣
Зависимости 👶👶👶
Для создания нашего приложения Redux нам нужны три пакета: redux
, который содержит логику для создания глобального состояния и взаимодействия с ним; react-redux
, который содержит логику React и компоненты более высокого порядка для интеграции глобального состояния с приложением React; и redux-thunk
, промежуточное ПО Redux для обработки асинхронных изменений состояния.
Инициализация глобального состояния 🎬
Для инициализации глобального состояния мы используем функцию createStore
из пакета redux
. В него мы передаем желаемые редукторы и промежуточное ПО.
Конечный результат выглядит так:
Функция createStore
- это загадка, но я не буду посвящать эту статью обсуждению распространенных жалоб разработчиков на кривую обучения Redux!
Подключение компонентов 🚈
Чтобы подключить компоненты к состоянию, мы должны обернуть приложение поставщиком глобального контекста состояния, а затем обернуть каждый подключенный компонент в компонент более высокого порядка, который ведет себя как потребитель глобального контекста состояния.
Конечный результат выглядит так:
Это очень много кода, чтобы использовать глобальное состояние. Несмотря на то, что пакет react-redux
ориентирован на интеграцию Redux с React, я лично не думаю, что вышеупомянутое имеет в виду подход React-first. Но я не буду посвящать эту статью обсуждению распространенных жалоб разработчиков на шаблон Redux!
Хотя этот шаг включает в себя загадочные действия fetchData
и incrementX
, я включил их в следующий раздел, поскольку они напрямую связаны с записью в глобальное состояние.
Чтение из глобального состояния и запись в него 👁🗨
Убрав весь этот шаблон, мы, наконец, можем использовать глобальное состояние! Мы получаем доступ и изменяем состояние через свойства подключенного компонента.
Конечный результат выглядит так:
Помимо действий, сам компонент очень легко читается!
Приложение ReactN 2️⃣
Теперь, когда мы увидели знакомую реализацию Redux, давайте посмотрим, как можно уменьшить сложность, указанную выше, и превратить ее в более читаемое и интуитивно понятное приложение React.
Зависимость D̶e̶p̶e̶n̶d̶e̶n̶c̶i̶e̶s̶
Установите пакет reactn
. Асинхронного промежуточного программного обеспечения нет. ReactN поддерживает промисы прямо из коробки. Вы можете удалить три вышеупомянутые зависимости Redux и вздохнуть с облегчением, когда ваше приложение упадет на 213 файлов зависимостей и имеет на 13% меньший размер производственного пакета, когда оно вместо этого использует ReactN.
Инициализация глобального состояния 🎬
Первый из громоздких шаблонов, пора инициализировать магазин и установить редукторы. Редукторы и действия в ReactN необязательны. Я включил их сюда только для честного сравнения, поскольку мы используем их в Redux. Если вы обнаружите, что редукторы слишком уж шаблонны, вы можете воздержаться от их использования. Альтернатива без редуктора будет предоставлена позже.
Мы используем setGlobal
, чтобы буквально просто установить глобальное состояние. Отлично подходит для инициализации.
Мы используем addReducer
, чтобы добавить редуктор. Обратите внимание, что ReactN не использует действия. Мы вызываем редуктор напрямую!
Мы сократили шаблонный код с 640 до 330 при добавлении действий! Подробнее об этом позже - для этого проекта я вообще не стал бы создавать fetchData
редуктор. Я включил его сюда только для симметрии с приложением Redux.
Подключение компонентов 🚈
ReactN не использует компоненты более высокого порядка. Чтобы подключить компоненты к глобальному состоянию, вы добавляете в файл один байт.
Я добавил n
в конец имени пакета, изменив react
на reactn
. Вот и все. Ваши Component
и PureComponent
теперь имеют доступ к глобальному состоянию.
Это было на 728 байтов меньше шаблона! На один HOC для всего приложения меньше и на один для каждого компонента меньше.
Чтение из глобального состояния и запись в него 👁🗨
Как мы используем глобальное состояние, если мы не указали ему, какие свойства нам нужны для нашего компонента? Помня о React, ReactN обрабатывает глобальное состояние как переменную-член - точно так же, как вы привыкли использовать с this.state
локального состояния.
Компонент выглядит точно так же, за исключением того, что для доступа к глобальному состоянию вы используете переменную-член this.global
вместо props. Компоненты более высокого порядка не требуются!
Вот и все! Компонент готов. Он полностью функциональный.
fetchData 🐶
Я уже упоминал, как по-разному обрабатывать действие выборки данных с помощью ReactN, поэтому я подробно остановлюсь здесь. ReactN не ограничивается действиями и редюсерами, как Redux. Глобальная переменная-член состояния ReactN предназначена для того, чтобы вести себя точно так же, как врожденная локальная переменная-член состояния React, и включает аналогичный метод this.setGlobal
, который ведет себя как this.setState
. Метод setGlobal
имеет дополнительные функции поддержки обещаний JavaScript.
Если fetchData
не вызывается из нескольких компонентов, он не дает нам возможности называть его редуктором, поэтому я бы вместо этого просто позвонил setGlobal
:
Получите index.html
, проанализируйте текст, создайте объект состояния и установите его.
Я бы не возражал против того, чтобы incrementX
reducer был просто методом в компоненте, который вызывает setGlobal
, поскольку он также не распределяется между компонентами.
Последнее сравнение 🏁
Я хотел показать два приложения бок о бок в их завершенном состоянии, поскольку приведенное выше относится только к фрагментам. Для приведенного ниже кода было бы лучше, если бы он был разбит на несколько файлов, но реальная проблема заключается в чтении, записи, понимании и обслуживании этого кода. Это касается не только вас, читатель, но и вашей команды, которая часто состоит из младших разработчиков.
Раньше: index.js с Redux 🔴
После: index.js с ReactN 💚
Раньше: App.js с Redux 🔴
После: App.js с ReactN 💚
Холодный, твердый факт ⛄
Независимо от того, считаете ли вы, что один метод легче читать, чем другой, одно здесь объективно. Вышеупомянутое приложение в производственной сборке занимает 531 736 байт с использованием ReactN. Его аналог Redux составляет 611 990 байт, что на 15% больше.
Разница, вероятно, уменьшается с увеличением объема, поскольку проект повторно использует больше действий и содержит значительно больше логики, не связанной с глобальным состоянием. Однако с увеличением объема вы увидите еще большее сокращение шаблонов!
Заключение 🔚
Если вы хотите внести свой вклад в этот проект, он с открытым исходным кодом на GitHub, и я был бы в полном восторге от дополнительных отзывов сообщества. Если вы хотите поэкспериментировать с этим проектом, просто npm install reactn --save
или yarn add reactn
.
Если вам понравилась эта статья, не стесняйтесь хлопать в ладоши. Это быстро, просто и бесплатно! Если у вас есть вопросы или полезные советы, оставьте их в комментариях ниже.
Чтобы читать больше моих колонок, вы можете подписаться на меня в LinkedIn и Twitter или проверить мое портфолио на CharlesStover.com.