Как подключить redux к react
Начало работы с Redux: подключение Redux к React
Russian (Pусский) translation by Ilya Nikov (you can also view the original English article)
Вам не нужно следовать предыдущим частям этой серии, чтобы этот урок имел смысл. Если вы хотите узнать, как использовать React с Redux, вы можете воспользоваться кратким обзором, приведенным ниже, а затем взять код из предыдущей части и начать с него.
Быстрый обзор
К концу этой статьи вы узнаете
Код для учебника доступен на GitHub в react-redux-demo. Возьмите код из ветки v2 и используйте его в качестве отправной точки для этого урока. Если вам интересно узнать, как приложение выглядит к концу этого урока, попробуйте ветку v3. Давайте начнем.
Проектирование иерархии компонентов: умный компонент против тупого
Это концепция, о которой вы, вероятно, слышали раньше. Но давайте кратко рассмотрим разницу между умными и глупыми компонентами. Напомним, что мы создали два отдельных каталога для компонентов, один из которых назвал containers/, а другой components/. Преимущество этого подхода заключается в том, что логика поведения отделена от представления.
Говорят, что компоненты представления глупы, потому что они обеспокоены тем, как все выглядит. Они отделены от бизнес-логики приложения и получают данные и обратные вызовы от родительского компонента исключительно через props. Им все равно, подключено ли ваше приложение к хранилищу Redux, если данные поступают из локального состояния родительского компонента.
Компоненты контейнера, с другой стороны, имеют дело с поведенческой частью и должны содержать очень ограниченную разметку и стиль DOM. Они передают данные, которые должны быть обработаны, для глупых компонентов в качестве props.
Я подробно рассмотрел эту тему в другом учебном пособии «Компоненты с состоянием и без состояния в React».
Двигаясь дальше, давайте посмотрим, как мы собираемся организовать наши компоненты.

Презентационные компоненты
Вот презентационные компоненты, которые мы будем использовать в этом уроке.
components/AddContactForm.jsx
Это HTML-форма для добавления нового контакта. Компонент получает обратные вызовы onInputChange и onFormSubmit в качестве props. Событие onInputChange запускается при изменении входного значения и onFormSubmit при отправке формы.
components/ContactList.jsx
components/ContactCard.jsx
Этот компонент получает объект контакта и отображает имя и изображение контакта. Для практических приложений может иметь смысл размещать изображения JavaScript в облаке.
Компоненты контейнера
Мы также собираемся создать компоненты контейнера barebones.
containers/Contacts.jsx
Функция returnContactList() извлекает массив объектов контактов и передает его компоненту ContactList. Поскольку returnContactList() извлекает данные из хранилища, мы пока оставим эту логику пустой.
containers/AddContacts.jsx
Мы создали три метода-обработчика, которые соответствуют трем действиям. Все они отправляют действия для обновления состояния. В методе рендеринга мы исключили логику для отображения/скрытия формы, потому что нам нужно получить состояние.
Теперь давайте посмотрим, как связать react и redux вместе
Библиотека react-redux
Привязки React по умолчанию недоступны в Redux. Сначала вам нужно будет установить дополнительную библиотеку react-redux.
Библиотека экспортирует только два API, которые вам нужно запомнить, компонент
Компонент провайдера
Такие библиотеки, как Redux, должны сделать доступными данные хранилища для всего дерева компонентов React, начиная с корневого компонента. Шаблон Provider позволяет библиотеке передавать данные сверху вниз. Приведенный ниже код демонстрирует, как поставщик волшебным образом добавляет состояние ко всем компонентам в дереве компонентов.
Демонстрационный код
Все приложение должно иметь доступ к хранилищу. Итак, мы оборачиваем провайдера вокруг компонента приложения и затем добавляем необходимые данные в контекст дерева. Потомки компонента получают доступ к данным.
Метод connect()
Демонстрационный код
Но чтобы это работало, вам нужна последняя строка в фрагменте кода выше.
Как соединить React и Redux?
Далее мы рассмотрим шаги, которые необходимо выполнить для подключения React и Redux.
Установка библиотеки react-redux
Установите библиотеку react-redux, если вы еще этого не сделали. Вы можете использовать NPM или yarn, чтобы установить ее.
Предоставьте хранилище вашему компоненту приложения
Сначала создайте хранилище. Затем сделайте объект хранилища доступным для вашего дерева компонентов, передав его в качестве prop
index.js
Подключите контейнеры React к Redux
Функция connect используется для привязки контейнера React к Redux. Это означает, что вы можете использовать функцию connect для:
Сначала импортируйте connect в AddContact.jsx.
mapStateToProps получает состояние хранилища в качестве аргумента. Он возвращает объект, который описывает, как состояние магазина отображается в ваших реквизитах. mapDispatchToProps возвращает похожий объект, который описывает, как действия по отправке отображаются на ваши реквизиты.
Наконец, мы используем connect для связывания компонента AddContact с двумя функциями следующим образом:
Обновите компоненты контейнера для использования реквизита
Если isHidden имеет значение false, форма отображается. В противном случае отображается кнопка.
Отображение контактов
Что дальше?
В следующем посте мы более подробно рассмотрим middleware и начнем рассылать действия, связанные с извлечением данных с сервера. Поделитесь своими мыслями в комментариях!
Как использовать пакет react-redux
Russian (Pусский) translation by Ilya Nikov (you can also view the original English article)
В приложениях Redux лучше всего провести различие между презентационными компонентами и компонентами контейнера. В этом видео я объясню, что это такое и как мы можем их использовать.
Я буду ссылаться на код, который мы уже создали в предыдущих частях курса, но вы должны быть в состоянии следовать за мной и видеть, что я делаю. Вы можете найти полный исходный код для курса на GitHub.
Как использовать пакет react-reduх
В предыдущих частях этого курса мы создали пример приложения с использованием React и Redux. Тем не менее, почти все наши компоненты должны работать с магазином либо путем чтения определенных состояний, либо путем отправки действий обратно в магазин. Помните, что в хранилище Redux хранится все состояние для всего вашего приложения. Это означает, что большинство, если не все из наших компонентов должны в некотором роде иметь доступ к хранилищу.

До сих пор у нас был глобальный объект хранилища, доступ к которому мы можем получить непосредственно в разделе, где мы присваиваем свойства нашей боковой панели.
Кроме того, если у нас много вложенных компонентов, то это означает, что если промежуточный компонент действительно не нуждается в хранилище, но один из его дочерних элементов нуждается, мы все равно должны передать его этому промежуточному компоненту, чтобы он мог передать состояние своему ребенку.
Теперь было бы неплохо, если бы мы могли предоставить всем нашим компонентам доступ к хранилищу без глобальной переменной и без ее передачи вручную.
Как работает react-redux
Одной из основных идей этого пакета является идея презентационных компонентов и компонентов контейнера. В принципе, мы можем разбить наше приложение на два набора компонентов.
Контейнеры, с другой стороны, знают о Redux, и они специально подписываются на состояние Redux и отправляют действия Redux. Мы можем создать компонент контейнера, просто обернув компонент отображения некоторыми из этих инструкций.
Практический пример: разделение компонентов боковой панели
Теперь давайте погрузимся и посмотрим, как это может работать. Мы собираемся использовать боковую панель в качестве примера компонента, который мы можем разделить на презентационные и контейнерные компоненты.
Сейчас вы скорее всего не понимаете, как мы собираемся разбить нашу боковую панель на два отдельных компонента. Но правда в том, что компоненты контейнера всегда будут обертывать презентационные компоненты. Фактически, часто у вас может быть презентационный компонент, который имеет только одно задание и которое должно быть обернуто одним конкретным компонентом контейнера. Именно это мы и сделаем с боковой панелью.
Установка react-redux
Когда библиотека будет установлена, мы можем продолжить импорт и импортировать ее с помощью import < Provider >from ‘react-redux’; в нашем основном файле app.js. В этом файле нам действительно нужен только компонент поставщика, предоставляемый нам react-redux.
Теперь компонент поставщика фактически является частью react-redux, который собирается взять наш магазин и передать его этим компонентам. Фактически, что происходит за кулисами: поставщик использует контекстную функцию React. Поэтому, если у вас есть немного более сложный опыт React, и вы уже играли с контекстом раньше, это может дать вам представление о том, как именно работает поставщик.
Поставщик фактически облегчаем использование магазина везде внутри приложения. Все, что нам нужно сделать, это обернуть наш компонент верхнего уровня в компоненте поставщика, как показано ниже:

И теперь наша заявка использует поставщика react-redux.
Использование функции connect()
Теперь я понимаю, что это звучит немного запутанно. Итак, давайте посмотрим, как это делается.

Презентационный компонент
Красота боковой панели, о которой мы уже писали, состоит в том, что она на самом деле уже является презентационным компонентом.
Как он считывает данные? Ну, он просто читает данные из свойств, которые мы ему дали. Как насчет изменения данных? Ну, он просто вызывает обратные вызовы из свойств. У нас есть три метода, и когда он вызывает их, данные в хранилище изменяются. И, наконец, конечно, да, это все написано вручную. И, как вы увидите через секунду, компоненты контейнера будут генерироваться с помощью react-redux.
Итак, у нас уже есть одна из двух частей, которые нам нужны: эта боковая панель, которая представляет собой презентационный компонент. Следующее, что мы хотим сделать, это взять эти определения свойств, которые мы предоставляем боковой панели, и вместо их определения здесь мы определим их как часть нашего контейнерного компонента.
Поэтому я просто собираюсь скопировать эти строки:

И я собираюсь вставить их наверху здесь:

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

Очистим код
Мы можем сделать несколько вещей, чтобы немного почистить здесь. Прежде всего, мы могли бы избавиться от этих фигурных скобок, которые являются блоком для этой функции, потому что у нас есть только одно утверждение, которое мы возвращаем. Но тогда, поскольку у нас есть только одна строка, мы можем избавиться от оператора return.
Однако теперь у нас есть фигурные скобки вокруг объектного литерала, и JavaScript будет думать, что это функциональный блок, поэтому мы обернем их в круглые скобки.
Мы можем сократить еще немного, потому что нам не нужен весь объект состояния, поэтому мы можем просто использовать синтаксис деструктурирования и сказать, что мы просто хотим иметь свойство decks и свойство addDeck этого объекта.
И вот более короткая версия нашей функции благодаря ES6.


Итак, теперь у нас есть все необходимое для создания нашего контейнерного компонента. У нас есть две функции, которые будут отображать наш объект состояния в нашей функции dispatch в свойства, необходимые этой функции. И у нас есть презентационный компонент, который ожидает эти свойства.
Итак, это был пакет react-redux в действии. Вы можете просмотреть исходные файлы курса на GitHub, чтобы узнать, как работает этот код в полном объеме.
Просомтрите полный курс
В полном курсе Современные веб приложения React и Redux,я покажу вам, как начать создавать современные веб-приложения с помощью React и Redux.
Начиная с нуля, вы будете использовать эти две библиотеки для создания полноценного веб-приложения. Вы начнете с простейшей возможной архитектуры и медленно создадите приложение, простепенно добавляя одну возможность за другой. Вы узнаете об основных понятиях, таких как инструменты, редукторы и маршрутизация. Вы также узнаете о более продвинутых методах, таких как умные и глупые компоненты, чистые компоненты и асинхронные действия. К концу вы создадите полное приложение для флэшкарточек.
По пути вы получите возможность повысить свои навыки ES6 (ECMAScript 2015) и изучить шаблоны и модули, которые лучше всего работают с React и Redux!
Вы также можете повысить свои навыки React с этими курсами:
Подключение Redux к React с помощью библиотеки
Redux – это отдельная от React сущность, которую можно использовать с любым фронт-энд фреймворком JavaScript или с обычным JavaScript. Однако нельзя отрицать, что React и Redux очень часто используются вместе. Чтобы облегчить настройку этой связки, библиотека React Redux предоставляет простые привязки.
API для привязок React Redux очень прост: в него входит компонент Provider, который делает хранилище доступным для нашего приложения, и функция подключения, создающая компоненты-контейнеры, которые могут считывать состояние из хранилища и отправлять действия (экшены).
Подготовка
Для начала давайте инициализируем проект React и установим все необходимые зависимости. Воспользуемся Create React App, чтобы создать тестовое приложение для управления закладками:
$ npx create-react-app fancy-bookmarks
Npx позволяет убедиться, что мы используем последнюю версию Create React Ap.
Теперь перейдем в каталог приложения и добавим пакеты redux и response-redux:
$ yarn add redux react-redux
# or, using npm:
$ npm install redux react-redux
Настройка Redux
После этого займемся настройкой Redux для нашего приложения. Поскольку здесь не будет подробных объяснений, советуем вам ознакомиться с нашим вступительным мануалом.
Во-первых, в файле actions/types.js установим некоторые типы действий:
А в файле actions/index.js – создатели действий:
Примечание: Обратите внимание, для генерирования случайных идентификаторов мы используем библиотеку uuid.
Нашему простому приложению нужен всего один редуктор, который мы определим в reducer/index.js:
Как видите, пока что мы работаем исключительно в области Redux и еще ничего не сделали, чтобы наше приложение React могло беспрепятственно взаимодействовать с хранилищем Redux. Этим мы и займемся дальше.
Компонент Provider
Мы будем использовать компонент Provider из библиотеки React Redux, чтобы обернуть основной компонент приложения и сделать хранилище Redux доступным из любого (подключенного) компонента-контейнера в дереве компонентов React (файл index.js):
Если бы мы использовали React Router, мы бы разместили компонент Provider вокруг компонента BrowserRouter.
Компоненты-контейнеры и функция connect
Теперь, когда хранилище Redux доступно в нашем приложении, мы можем создать компоненты-контейнер (также известные как подключенные компоненты), которые будут иметь доступ для чтения из хранилища или отправки действий. Мы создадим два компонента-контейнера: AddBookmark и BookmarkList, а компонент App будет использовать их. С учетом вышеописанных обновлений файл App.js будет выглядеть следующим образом:
Теперь напишем наш первый подключенный компонент, BookmarksList, в файле containers/BookmarksList.js:
Мы используем функцию connect из библиотеки React Redux и передаем функции mapStateToProps и mapDispatchToProps. Затем мы вызываем возвращенную функцию с компонентом, который хотим подключить.
mapStateToProps получает текущее значение состояния и должен вернуть объект, который делает части состояния доступными в качестве свойств для подключенного компонента. В данном примере есть только состояние bookmarks, но представить сценарий, в котором несколько частей состояния отображаются на разные свойства, довольно просто. Например:
mapStateToProps получает метод диспетчеризации хранилища и должен вернуть объект, который делает некоторые обратные вызовы доступными в качестве свойств. Они, в свою очередь, отправляют желаемые действия в хранилище.
Далее мы напишем компонент AddBookmark в файле containers/AddBookmark.js:
Этому компоненту не нужно читать данные из хранилища, поэтому в качестве первого аргумента функции connect мы передаем null.
Вы также заметите, что этот второй подключенный компонент сам по себе ничего не отображает, вместо этого вся визуализация пользовательского интерфейса оставлена презентационному компоненту NewBookmark.
Презентационные компоненты намного проще, они не имеют прямого доступа к хранилищу. Вместо этого они получают от компонентов-контейнеров свойства со значениями из состояния или обратные вызовы, которые вызывают создателей действий. Им не нужно ничего знать о Redux, по сути они являются просто функцией предоставленных им свойств. Презентационные компоненты просты в написании, их легко использовать повторно и тестировать.
Например, вот так выглядит презентационный компонент Bookmark, который отображает одну закладку (файл components/Bookmark.js):
Как видите, в качестве свойств он получает bookmark, а также обратный вызов onDelete.
А вот NewBookmark (файл components/NewBookmark.js) – не чисто презентационный, а скорее гибридный компонент, поскольку он содержит некоторое локальное состояние для входных значений. Тем не менее, этот компонент вообще не знает о Redux.
Вот и все! Наше простое приложение для управления закладками работает, получает данные из хранилища и отправляет действия.
Чтобы узнать больше, советуем заглянуть в официальную документацию.
Использование с React
Для начала стоит подчеркнуть, что Redux не имеет отношения к React. Вы можете создавать Redux-приложения c помощью React, Angular, Ember, jQuery или обычного JavaScript.
И все-таки, Redux работает особенно хорошо с такими фреймворками, как React и Deku, потому что они позволяют вам описать UI как функцию состояния, и, кроме того, Redux умеет менять состояние (state) приложения в ответ на произошедшие экшены (actions).
Мы будем использовать React для создания нашего простого приложения todo и рассмотрим основы использования React с Redux.
Примечание: смотрите официальную документацию React-Redux на https://react-redux.js.org для полного руководства о том, как использовать Redux и React вместе.
Установка React Redux
React bindings не включены в redux по умолчанию. Вам нужно установить их явно:
Презентационные компоненты и компоненты-контейнеры (Presentational and Container Components)
React байндинг для Redux отделяют презентационные компоненты от компонент-контейнеров Такой подход может облегчить понимание вашего приложения и упростить повторное использование компонентов. Вот краткое изложение различий между презентационными и контейнерными компонентами (но если вы незнакомы, мы рекомендуем вам также прочитать оригинальную статью Дэна Абрамова, описывающую концепцию презентационных и контейнерных компонентов):
| Компоненты-представления | Компоненты-контейнеры | |
|---|---|---|
| Назначение | Как выглядит (разметка, стили) | Как работает (загрузка данных, обновление состояния) |
| Знают о Redux | Нет | Да |
| Читают данные | Читают данные из props | Подписываются на Redux-состояние |
| Изменяют данные | Вызывают колбеки из props | Отправляют Redux-экшены |
| Написаны | Руками | Обычно генерируются React Redux |
Большинство компонентов, которые мы напишем, будут представлениями, но чтобы соединить их с Redux-состоянием, нам потребуется сгенерировать несколько контейнеров. Это и дальнейшее описание не означает, что компоненты-контейнеры должны быть расположены ближе к вершине дерева компонентов. Если компонент-контейнер становится слишком сложным, т.е. он имеет сильную вложенность презентационных компонентов, с бесчисленным количеством обратных вызовов, передающихся вниз, используйте еще один контейнер в дереве компонентов, как отмечено в FAQ.
Проектирование иерархии компонентов
Помните, как мы спроектировали структуру корневого объекта состояния? В этот раз мы спроектируем иерархию UI-компонентов, которая будет соответствовать этой структуре. С такого рода задачей Вы можете столкнуться, разрабатывая и не Redux-приложение. Thinking in React — великолепное руководство, которое поясняет весь процесс решения этой задачи.
Наш бриф довольно прост. Мы хотим показать список дел (todo). По клику мы должны зачеркнуть дело, что будет означать, что оно выполнено. Также мы хотим показать поле ввода, с помощью которого пользователь сможет добавить новое дело в список. В футере должны быть переключатели, с помощью которых мы будем показывать все дела, только завершенные, только не завершенные.
Разработка презентационных компонентов
Из этого брифа получаются следующие представления и их props:
Они описывают вид, но не знают откуда приходят данные или как изменить их. Они только рендерят то, что им дают. Если вы мигрируете с Redux на что-нибудь другое, вы сможете оставить эти компоненты точно такими же. Они не зависят от Redux.
Проектирование компонент-контейнеров
Проектирование других компонент
Иногда трудно сказать, каким должен быть компонент — представлением или контейнером. Например, иногда форма и функция действительно соединены вместе, как в случае с этим миниатюрным компонентом:
Технически, мы могли бы разделить его на два компонента, но это может быть слишком рано на данном этапе. Вполне допустимо смешивать представление и логику, когда компонент очень маленький. Как только он вырастет, станет более понятно как разделить его, так что мы пока оставим его смешанным.
Реализуем компоненты
Давайте напишем компоненты! Мы начнем с представлений, так что пока нам не нужно думать о привязке к Redux.
Компоненты-представления
Это все обычные React-компоненты, поэтому мы не будем изучать их детально. Мы пишем функциональные stateless-компоненты, пока нам не потребуются локальное состояние или lifecycle-методы. Это не значит, что представления должны быть функциями, просто так легче. Если/когда вам потребуется добавить локальное состояние, lifecycle-методы или оптимизацию производительности, вы сможете конвертировать их в классы.
components/Todo.js
components/TodoList.js
components/Link.js
components/Footer.js
components/App.js
Компоненты-контейнеры
Наконец, мы создаем VisibleTodoList вызывая connect() и передал эти две функции:
Это основы React Redux API, но там есть несколько комбинаций и мощных опций, поэтому мы рекомендуем вам подробно изучить эту документацию. В случае если вы переживаете, что mapStateToProps создает слишком много новых объектов, то вам будет полезно узнать о вычислении полученных данных с reselect.
Остальные компоненты-контейнеры вы найдете ниже:
containers/FilterLink.js
containers/VisibleTodoList.js
Другие Компоненты
containers/AddTodo.js
Напомним, как было упомянуто ранее и представление, и логика для компонента AddTodo смешаны в одном определении.
Связывание контейнеров внутри компонента
components/App.js
Передаем стор
index.js
Следующие шаги
Прочитайте полный исходный код для этого руководства для лучшего усваивания полученных знаний. А затем прямиком в руководство для опытных для изучения обработки сетевых запросов и роутинга
Вам также нужно потратить некоторое время, чтобы прочитать документы React-Redux, чтобы получить лучшее понимание того, как использовать React и Redux вместе.


















