Redux что это javascript

С 0 до 1. Разбираемся с Redux

Когда вышла версия 1.0 Redux, я решил потратить немного времени на серию рассказов о моем опыте работы с ним. Недавно я должен был выбрать “реализацию Flux” для клиентского приложения и до сих пор с удовольствием работаю с Redux.

Почему Redux?

Redux позиционирует себя как предсказуемый контейнер состояния (state) для JavaScript приложений. Редакс вдохновлен Flux и Elm. Если вы раньше использовали Flux, я советую прочитать, что Redux имеет с ним общего в разделе «Предшественники» новой (отличной!) документации.

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

Конечно, вы можете найти больше информации о Redux, его архитектуре и роли каждого компонента в документации.

Создаем список друзей с React и Redux

Сегодня мы сфокусируемся на пошаговом создании вашего первого приложения, использующего Редакс и Реакт: создадим простой список друзей с нуля.

Вы можете найти готовый код здесь.

Для кого?

Эта статья написана для людей, не имеющих опыта работы с Redux. Опыт разработки с Flux также не обязателен. Я буду давать ссылки на документы, когда мы будем сталкиваться с новыми понятиями.

1. Установка

Автор Redux, Даниил Абрамов, создал отличную сборку для разработки с React, Webpack, ES6/7 и React Hot Loader, которую вы можете найти здесь.

Есть сборки уже с установленным Redux, но, я думаю, важно понять роль каждой библиотеки.

Теперь вы можете открыть приложение по адресу http://localhost:3000. Как вы видите, «hello world» готов!

1.1 Добавим redux, react-redux и redux-devtools

Нам нужно установить три пакета:

1.2 Структура директорий

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

Мы будет видеть более детально роль каждой из директорий, когда будем создавать приложение. Мы переместили App.js в директорию containers, так что нужно будет настроить импорт statement в index.js.

1.3 Подключаем Redux

Нам нужно включить devtools только для окружения разработки, так что модифицируем webpack.config.js как здесь:

Мы делаем здесь две вещи. Мы переопределяем createStore используя созданную функцию, которая позволяет нам применять множественные store enhancers, таких как devTools. Мы также включаем функцию renderDevTools, которая рендерит DebugPanel.

Сейчас нам нужно модифицировать App.js для соединения с redux. Для этого мы будем использовать Provider из react-redux. Это сделает наш экземпляр хранилища доступным для всех компонентов, которые располагаются в Provider компоненте. Не нужно беспокоится о странно выглядящей функции, ее цель использовать “контекст” функции Реакта для создания хранилища, доступного для всех детей (компонентов).

Для создания хранилища мы используем createStore функцию, которую мы определили в devTools файле, как map всех наших редьюсеров.

В нашем приложении App.js — внешняя обертка для Redux и FriendListApp — корневой компонент для нашего приложения. После создания простого ‘Hello world’ в FriendListApp.js, мы можем наконец запустить наше приложение с redux и devTools. Вы должен получить это (без стилей).

Хотя это просто ‘Hello world’ приложение, у нас включен Hot Reloading, т.е. вы можете модифицировать текст и получать автоматическое обновление на экране. Как вы можете видеть, devtools справа показывает пустые хранилища. Заполним их!

2. Создаем приложение

Теперь, когда сделаны все настройки, мы можем сфокусироваться на самом приложении.

2.1 Действия и генераторы действий

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

Генераторы действий — функции, которые создают действия. В Redux генераторы действий являются чистыми функциями, что делает их портативными и простыми для тестирования, т.к. они не имеют сайд-эффектов.

Мы поместим их в папку действий, но не забывайте, что это разные понятия.

Как видите, действия довольно минималистичны. Чтобы добавить элемент, мы сообщаем все свойства (здесь мы имеем дело только с name), а для других мы ссылаемся на id. В более сложном приложении, мы, возможно, имели бы дело с асинхронными действиями, но это тема для другой статьи…

2.2 Редьюсеры

Мы, для начала, определяем вид состояния нашего приложения в initialState :

Состоянием может быть все, что мы захотим, мы можем просто сохранить массив друзей. Но это решение плохо масштабируется, так что мы будем использовать массив id и map друзей. Об этом можно почитать в normalizr.

Теперь нам нужно написать актуальный редьюсер. Мы воспользуемся возможностями ES6 для задания аргументов по умолчанию для обработки случаев, когда состояние не определено. Это поможет понять как записать редьюсер, в данном случае я использую switch.

Если вы не знакомы с синтаксисом ES6/7, то возможно вам будет трудно это прочесть. Т.к. нам нужно вернуть новое состояние объекта, как правило используют Object.assign или Spread operator.

Что здесь происходит: мы определяем новый id. В реальном приложении мы, возможно, возьмем его с сервера или, как минимум, убедимся, что он уникальный. Затем мы используем concat чтобы добавить этот новый id в наш id-лист. Concat добавит новый массив и не изменит оригинальный.

Читайте также:  Product placement что это

Как вы можете видеть, несмотря на синтаксис, который может сначала смутить, логика проста. Вы задаете состояние и получаете назад новое состояние. Важно: ни в одной точке этого процесса не изменять предыдущее состояние.

Окей, давайте вернемся и создадим редьюсеры для двух других действий:

Вы также можете заметить, что spread оператор позволяет нам манипулировать только теми состояниями, которое нам нужно изменить.

Redux не важно, как вы храните данные, так что можно использовать Immutable.js.

Теперь вы можете поиграть с хранилищем минуя интерфейс, путем вызова dispatch вручную в нашем App.js.

Вы увидите в devTools действия, с ними можно поиграть в реальном времени.

3. Создаем интерфейс

Т.к. этот урок не об этом, я пропустил создание React-компонентов и сфокусировался только на Redax. Мы имеем три простых компонента:

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

Здесь FriendListApp будет единственным “умным” компонентом.

Это часть нового синтаксиса ES7, называемая декоратор. Это удобный способ вызова функции высшего порядка. Будет эквивалентна connect(select)(FriendListApp); где select — функция, которая возвращает то, что мы здесь сделали.

То, что случится дальше — стандартный подход для React. Мы привяжем функции к onClick, onChange или onKeyDown свойствам, чтобы обработать действия пользователя.

Если вы заинтересовались, как это сделать, ты можете посмотреть весь код.

Сейчас вы можете почувствовать магию работы redux/react приложения. Как изображено на GIF, вы логгируете все действия.
Разрабатывать удобней, когда ты можешь производить какие-то действия, находить баги, возвращаться, исправлять их и повторять уже исправленную последовательность…

Источник

Redux. Простой как грабли

Мне уже доводилось заглядывать в репозиторий библиотеки redux, но откуда-то появилась мысль углубиться в его реализацию. Своим в некотором роде шокирующим или даже разочаровывающим открытием я хотел бы поделиться с сообществом.

TL;DR: базовая логика redux помещается в 7 строк JS кода.

О redux вкратце (вольный перевод заголовка на гитхабе):

Redux — библиотека управления состоянием для приложений, написанных на JavaScript.

Она помогает писать приложения, которые ведут себя стабильно/предсказуемо, работают на разных окружениях (клиент/сервер/нативный код) и легко тестируемы.

Я склонировал репозиторий redux, открыл в редакторе папку с исходниками (игнорируя docs, examples и прочее) и взялся за ножницы клавишу Delete:

… потому что мог. Ну или потому что поленился писать для них примеры. Но без корнер-кейсов они ещё менее интересны, чем то, что ждёт вас впереди.

А теперь давайте разберём то, что осталось

Пишем redux за 7 строк

Весь базовый функционал redux умещается в малюсенький файлик, ради которого вряд ли кто-нибудь будет создавать github репозиторий 🙂

Так устроен redux. 18 страниц вакансий на HeadHunter с поисковым запросом «redux» — люди, которые надеются, что вы разберетесь в 7 строках кода. Всё остальное — синтаксический сахар.

С этими 7 строками уже можно писать TodoApp. Или что угодно. Но мы быстренько перепишем TodoApp из документации к redux.

Уже на этом этапе я думал бросить микрофон со сцены и уйти, но show must go on.
Давайте посмотрим, как устроен метод.

combineReducers

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

Используется он так:

Дальше использовать этот store можно так же, как предыдущий.

Разница моего примера и описанного в той же документации к TodoApp довольно забавная.

В документации используют модный синтаксис из ES6 (7/8/∞):

и соответственно переименовывают todoReducer в todos и counterReducer в counter. И многие в своём коде делают то же самое. В итоге разницы нет, но для человека, знакомящегося с redux, с первого раза эта штука выглядит магией, потому что ключ части состояния (state.todos) соответствует функции, названной также только по желанию разработчика (function todos()<>).

Если бы нам нужно было написать такой функционал на нашем micro-redux, мы бы сделали так:

Этот код плохо масштабируется. Если у нас 2 «под-состояния», нам нужно дважды написать (state, action), а хорошие программисты так не делают, правда?

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

Однако реализация метода combineReducers довольно простая (напоминаю, это если убрать валидацию и вывод ошибок) и самую малость отрефакторить на свой вкус:

Мы добавили к нашему детёнышу redux ещё 9 строк и массу удобства.

Перейдём к ещё одной важной фиче, которая кажется слишком сложной, чтобы пройти мимо неё.

applyMiddleware

middleware в разрезе redux — это какая-то штука, которая слушает все dispatch и при определенных условиях делает что-то. Логирует, проигрывает звуки, делает запросы к серверу,… — что-то.

В оригинальном коде middleware передаются как дополнительные параметры в createStore, но если не жалеть лишнюю строчку кода, то использование этого функционала выглядит так:

При этом реализация метода applyMiddleware, когда ты потратишь 10 минут на ковыряние в чужом коде, сводится к очень простой вещи: createStore возвращает объект с полем «dispatch». dispatch, как мы помним (не помним) из первого листинга кода, — это функция, которая всего лишь применяет редюсер к нашему текущему состоянию (newState = reducer(state, action)).
Так вот applyMiddleware не более чем переопределяет метод dispatch, добавляя перед (или после) обновлением состояния какую-то пользовательскую логику.

Читайте также:  Номер карты токио сити для скидки

Возьмём, например, самый популярный middleware от создателей redux — redux-thunk

Его смысл сводится к тому, что можно делать не только

но и передавать в store.dispatch сложные функции

И теперь, когда мы выполним команду

я понимаю, что конструкция выглядит жутковато, но её тоже просто нужно вызвать пару раз с произвольными параметрами и вы осознаете, что всё не так страшно, это просто функция, возвращающая функцию, возвращающую функцию (ладно, согласен, страшно)

Напомню, оригинальный метод createStore выглядел так

То есть он принимал атрибуты (reducer, initialState) и возвращал объект с ключами < dispatch, getState >.

Оказалось, что реализовать метод applyMiddleware проще, чем понять, как он работает.
Мы берём уже реализованный метод createStore и переопределяем его возвращаемое значение:

Вывод

Под капотом redux содержатся очень простые логические операции. Операции на уровне «Если бензин в цилиндре загорается, давление увеличивается». А вот то, сможете ли вы построить на этих понятиях болид Формулы 1 — уже решайте сами.

Источник

Начало работы с Redux: почему Redux?

Russian (Pусский) translation by Liliya (you can also view the original English article)

Когда вы изучаете React, вы почти всегда будете слышать, как люди говорят, насколько велик Redux, и что вы должны его попробовать. Экосистема React растет быстрыми темпами, и существует так много библиотек, которые вы можете подключить с помощью React, таких как flow, redux, middlewares, mobx и т. д.

В React легко обучаться, но привыкание к всей экосистеме React требует времени. Этот учебник представляет собой введение в один из неотъемлемых компонентов экосистемы React-Redux.

Основная терминология Non-Redux

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

Чистая функция

Например, вот чистая функция, которая возвращает сумму двух чисел.

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

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

Наблюдаемые побочные эффекты

Однако, если чистая функция вызывает другую чистую функцию, тогда эту функцию можно рассматривать как чистую. Вот некоторые из общих побочных эффектов:

Контейнерные и презентационные компоненты

Разделение архитектуры компонента на два полезно при работе с приложениями React. Вы можете классифицировать их по двум категориям: компоненты контейнера и презентационные компоненты. Они также широко известны как умные и немые компоненты.

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

Отменяемые и неизменяемые объекты

Изменчивый объект можно определить следующим образом:

Почему Redux?

Официальная страница определяет Redux следующим образом:

Redux является предсказуемым контейнером состояний для приложений JavaScript.

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

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

С помощью React каждый компонент имеет локальное состояние, доступное изнутри компонента, или вы можете передать их как реквизиты дочерним компонентам. Обычно мы используем состояние для хранения:

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

Иерархия компонентов базового приложения

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

Эскиз приложения среднего размера

Почему вы должны использовать Redux?

Вот с чем вы можете встретиться работая с React.

Это то, что я лично испытал с React, и многие другие разработчики согласятся. React- это библиотека представлений, и дело не в React чтобы управлять состоянием. Мы ищем принцип разделения идей.

Redux помогает вам отделить состояние приложения от React. Redux создает глобальный магазин, который находится на верхнем уровне вашего приложения и передает состояние всем остальным компонентам. В отличие от Flux, Redux не имеет нескольких объектов хранилища. Все состояние приложения находится внутри этого объекта-хранилища, и вы могли бы поменять слой вида на другую библиотеку с неповрежденным хранилищем.

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

Читайте также:  боюсь всего нового в жизни

Теперь, когда мы знаем, почему Redux полезен, давайте погрузимся в архитектуру Redux.

Redux Архитектура

Когда вы изучаете Redux, есть несколько основных понятий, к которым вам нужно привыкнуть. На приведенном ниже рисунке описывается архитектура Redux и все составные вместе.

Что такое Redux в двух словах

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

Для настройки сервера разработки используйте приложение create-react-app или вашу любимую конфигурацию webpack. Поскольку Redux является независимым государственным управлением, мы еще не собираемся подключаться к React. Поэтому удалите содержимое index.js, и мы будем играть с Redux для остальной части этого урока.

Хранилище

В хранилище находится один большой объект JavaScript, который содержит несколько пар ключ-значение, которые представляют текущее состояние приложения. В отличие от объекта State в React, который разбрызгивается через разные компоненты, у нас есть только один магазин. Хранилище обеспечивает состояние приложения, и каждый раз, когда состояние обновляется, просмотр rerenders.

Однако вы никогда не сможете изменить или изменить хранилище. Вместо этого вы создаете новые версии хранилища.

Из-за этого вы можете путешествовать во времени во всех штатах с момента загрузки приложения в свой браузер.

В хранилище есть три способа связи с остальной архитектурой. Вот они:

Давайте создадим хранилище. Redux имеет метод createStore для создания нового хранилища. Вам нужно передать ему редуктор, хотя мы не знаем, что это такое. Поэтому я просто создаю функцию, называемую редуктором. Вы можете указать второй аргумент, задающий начальное состояние хранилища.

src/index.js

Теперь мы будем слышать любые изменения в хранилище, а затем console.log() текущее состояние хранилища.

Итак, как мы обновляем хранилище? В Redux есть что-то, называемое действиями, которые делают это возможным.

Создатели Action / Action

Действия также представляют собой обычные объекты JavaScript, которые отправляют информацию из вашего приложения в хранилище. Если у вас очень простой счетчик с кнопкой инкремента, нажатие на него приведет к срабатыванию действия, которое выглядит следующим образом:

Они являются единственным источником информации в магазине. Состояние хранилища изменяется только в ответ на действие. Каждое действие должно иметь свойство типа, которое описывает, что намеревается сделать объект действия. Помимо этого, структура действия полностью зависит от вас. Однако сохраните свое действие маленьким, потому что действие представляет собой минимальный объем информации, необходимой для преобразования состояния приложения.

Например, в приведенном выше примере свойство type установлено в «INCREMENT», а также добавлено дополнительное свойство полезной нагрузки. Вы можете переименовать свойство полезной нагрузки в нечто более значимое или, в нашем случае, опустить его полностью. Вы можете отправить действие в хранилище, как это.

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

Итак, чтобы обновить состояние счетчика, вам нужно будет отправить действие incrementCount следующим образом:

Если вы направляетесь в консоль браузера, вы увидите, что он работает, частично. Мы получаем неопределенность, потому что мы еще не определили редуктор.

Итак, теперь мы рассмотрели действия и магазин. Однако нам нужен механизм для преобразования информации, предоставляемой действием, и преобразования состояния хранилища. Редукторы служат для этой цели.

Переходники

Действие описывает проблему, и редуктор отвечает за решение проблемы. В предыдущем примере метод incrementCount возвратил действие, которое предоставило информацию о типе изменения, который мы хотели бы сделать в строении. Редуктор использует эту информацию для фактического обновления состояния. В документах есть большая точка, которую вы всегда должны помнить при использовании Redux:

Учитывая те же аргументы, редуктор должен вычислить следующее состояние и вернуть его. Без сюрпризов. Никаких побочных эффектов. Нет вызовов API. Никаких мутаций. Просто расчет.

Это означает, что редуктор должен быть чистой функцией. Учитывая набор входов, он всегда должен возвращать тот же результат. Помимо этого, он не должен делать ничего больше. Кроме того, редуктор не является местом для побочных эффектов, таких как вызов AJAX или выборка данных из API.

Давайте заполним редуктор для нашего счетчика.

Вот создатель действия.

Наконец, отправьте его в хранилище.

Подведем итоги

Этот учебник должен был стать отправной точкой для управления состоянием с помощью Redux. Мы рассмотрели все необходимое, чтобы понять основные концепции Redux, такие как хранилище, действия и редукторы. К концу обучения мы также создали рабочий демонстрационный demo счетчик. Хотя это было не так уж много информации, но мы узнали, как все части головоломки подходят друг другу.

За последние пару лет React стал популярным. Фактически, у нас есть ряд предметов на рынке, доступных для покупки, просмотра, реализации и т. д. Если вы ищете дополнительные ресурсы вокруг React, не стесняйтесь их проверять.

В следующем уроке мы будем использовать то, что мы узнали здесь, для создания приложения React с использованием Redux. Оставайтесь с нами. Поделитесь своими мыслями в комментариях.

Источник

Развивающий портал