Redux - это библиотека управления состоянием, которая становится все более популярной, но ей нужно научиться. Есть определенные технические термины, которые сбивают с толку людей, когда они впервые начинают изучать Redux. Если вы чувствуете, что вам нужно немного больше понять Redux, я предлагаю попробовать мою статью Redux CRUD. Это длинная статья, в которой рассматриваются важные концепции Redux, такие как действия, редукторы и хранилища, при создании приложения на основе CRUD. В этом посте, который является продолжением предыдущей статьи о Redux, я попытаюсь объяснить, что такое Redux Thunk, создав приложение Github Search.

Итак, давайте начнем. Первое, что вам понадобится, это create-react-app, поэтому убедитесь, что оно установлено на вашем компьютере, если вы не набираете следующую команду в терминале:

npm install -g create-react-app

Почему вы используете npm, а почему не пряжу? Старые привычки. Теперь, когда у вас есть настроенный инструмент, давайте создадим новый проект.

Введите в терминал следующее:

create-react-app github-search

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

cd github-search

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

cd src

rm App.css App.test.js logo.svg registerServiceWorker.js

Как только это будет сделано, вернитесь в текстовый редактор и внесите некоторые изменения в файл index.js. Изменения должны быть следующими:

Теперь перейдите к App.js и внесите следующие изменения:

Теперь вернитесь в корневой каталог проекта и введите следующее:

npm start

Это дает нам следующее:

Теперь давайте установим redux, redux-thunk и react-redux.

npm install redux redux-thunk react-redux

Теперь создайте новую папку в каталоге src и назовите ее actions. Затем создайте файл в этой папке и назовите его fetchAction.js. Как только это будет сделано, создайте в каталоге src еще одну папку с именем reducers и создайте в ней файл с именем index.js. Как только все это будет сделано в каталоге src, создайте файл с именем store.js.

Теперь напишем код. Внутри store.js напишите следующее:

Мы импортируем функцию createStore и функцию applyMiddleware. Что такое промежуточное ПО? Что ж, это не что иное, как кусок кода, который находится между вашими действиями и вашими редукторами. Он требует, чтобы ваши действия что-то с ним сделали, прежде чем передать его редуктору. Думайте об этом как о посреднике.

Теперь createStore используется для создания хранилища redux, а applyMiddleware будет использоваться для добавления промежуточного программного обеспечения преобразователя. Затем у нас есть оператор импорта из каталога redurs, пока его игнорируем. По сути, это импорт редуктора, который нам понадобится для этого приложения. Здесь имя редуктора asyncReducer. Затем мы импортируем thunk из пакета redux-thunk.

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

Теперь, когда у нас есть хранилище, давайте напишем редуктор для этого приложения. Вернитесь в index.js в каталоге редукторов. Обратите внимание: перейдите в index.js в папке редюсеров, а не в корневой index.js файл. Там напишите следующий код:

Здесь у нас есть довольно простой редуктор. Что здесь интересно, так это форма объекта состояния. Состояние содержит два свойства: одно - userData, а другое - isFetching. userData - это объект, который будет содержать всю связанную с пользователем информацию, которую мы получим из нашего API. Свойство isFetching будет использоваться для загрузки индикатора загрузки в зависимости от того, когда сделан запрос API. isError используется для отображения сообщения об ошибке в случае, если мы не получаем обратно какие-либо пользовательские данные.

Вернитесь к index.js и внесите следующие изменения:

Здесь мы импортировали store, который мы создали ранее внутри store.js. Мы также используем компонент Provider, который позволяет нам получать доступ к состоянию хранилища из наших компонентов. Следовательно, мы передаем компонент App, который является корневым компонентом, в провайдер и передаем хранилище как опору.

Теперь вернемся к fetchAction.js, который находится внутри нашей папки действий, и напишем следующий код.

Здесь мы используем создателей действий. Теперь создатели действий - это просто функции, возвращающие объект действия. Здесь у нас есть три создателя действий, каждый из которых возвращает действие. Немного напомню перед тем, как двигаться дальше. Действия - это простые старые объекты javascript, которые имеют обязательное свойство типа. Это свойство определяет, какое действие / событие происходит в приложении. Создатель первого действия fetch_post отвечает за запуск запроса на выборку. Он будет использоваться в основном для отображения индикатора загрузки.

Второй создатель действия receive_post будет вызван, когда мы получим данные из github. Наконец, receive_error - это создатель действий, который будет вызываться только тогда, когда у нас возникнет ошибка при получении наших данных с серверов github.

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

function say() {
  return function something() {
    //code here
  };
}

Вышеупомянутая функция say() является преобразователем, потому что в данном случае она возвращает другую функцию something(). Вы можете спросить, насколько это полезно. Мы знаем, что в редукторах redux - это чистые функции, поэтому мы не можем выполнять какие-либо асинхронные операции внутри редукторов, а действия - это просто старые объекты. Теперь наш метод диспетчеризации внутри хранилища принимает объект действия в качестве своего параметра, что делает промежуточное ПО redux thunk состоит в том, что если, скажем, создатель действия возвращает функцию вместо объекта, он просто выполняет эту возвращаемую функцию.

Теперь возвращающая функция может принимать два параметра. Это dispatch и getState. Это здорово, потому что с dispatch мы можем вызывать других создателей действий. Итак, теперь все, что мы делаем для асинхронных операций, - это делаем все, что будет асинхронно внутри возвращаемой функции, а затем вызывать соответствующих создателей действий, когда данные возвращаются, передавая новые данные, которые мы получаем из API. Другие соответствующие создатели действий в этом случае receive_post затем передают эти новые данные в объекте действия редуктору, и затем редуктор может обновить состояние приложения новыми данными.

Имея это в виду, давайте изменим код в fetchAction.js следующим образом:

Итак, теперь у нас есть новая функция внизу под названием thunk_action_creator. Эта функция принимает в качестве параметра имя пользователя. Сначала мы берем имя пользователя и очищаем данные, например удаляем пробелы, а затем помещаем их в переменную user. После этого у нас есть первое использование диспетчеризации, в котором мы вызываем создателя действия fetch_post, который будет использоваться для установки нашего индикатора загрузки, как указано ранее. Затем мы возвращаем функцию из thunk_action_creator. Эта функция имеет доступ к диспетчеризации и методам getState объекта хранилища. Здесь мы возвращаем что-то из вызова fetch. В параметре мы передаем URL-адрес, который будет использоваться для выборки пользователей, и передаем имя пользователя, которое будет предоставлено пользователем. Наконец, когда данные возвращаются, мы вызываем другого создателя действия, используя диспетчерскую receive_post, которая принимает недавно полученный data от API и передает его в качестве аргумента. Наконец, если возвращаемые данные имеют свойство сообщения со значением Not Found, мы просто выдаем новую ошибку, заявляя, что пользователь с таким именем пользователя не существует, и поэтому мы перехватываем эту ошибку и вызываем receive_error, который будет использоваться для установки наш флаг ошибки.

После этого давайте вернемся к функции редуктора и добавим еще код.

У нас есть три корпуса переключателей. Первый FETCH_USER используется для установки индикатора загрузки. Следующий FETCHED_USER используется для установки данных, полученных от API в объекте userData. Наконец, у нас есть RECEIVE_ERROR, который устанавливает флаг ошибки в значение true. Вот ссылка на Назначение объекта, если вы чувствуете, что нуждаетесь в переподготовке.

Теперь давайте вернемся к App.js, приступим к созданию пользовательского интерфейса и подключим все это.

Я уже подготовил для этого следующие стили:

Поместите весь этот код в index.css. Обратите внимание, что я использую здесь собственный шрифт, поэтому вам, возможно, придется попробовать что-нибудь еще. Теперь, если мы вернемся и проверим браузер, он должен выглядеть так:

Теперь, если мы введем что-то во входные данные и нажмем «Отправить», мы увидим, что мы также можем захватывать пользовательские данные внутри консоли.

Теперь я знаю, что мог бы сделать форму управляемым компонентом и использовать onChangehandler. Я использовал refs, так как они, по крайней мере, для меня проще понять. Вы можете вернуться к желаемому вами способу.

Теперь вернемся к App.js и подключим его к нашему магазину.

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

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

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

Здесь много чего происходит. Сначала мы используем наш thunk_action_creator внутри нашего handleSubmit, куда мы отправляем его, передавая имя пользователя, которое мы получили от пользователя.

Внутри компонента приложения после элемента формы мы проверяем, установлен ли флаг isFetching из нашего состояния в значение true, если да, мы показываем индикатор загрузки. Затем мы проверяем, есть ли ошибки при извлечении данных, если да, мы показываем сообщение об ошибке. Наконец, мы проверяем, является ли объект userData пустым или нет. В противном случае мы визуализируем <UserInfo>component и передаем объект userData как user prop.

Внутри компонента UserInfo у нас есть следующий код:

Просто базовый компонент, который принимает объект userData и показывает его на экране. Теперь, если мы вернемся в браузер и снова введем имя пользователя, мы увидим следующее:

Теперь я знаю, что все это перебор для создания такого простого приложения. Мы могли бы сделать это с помощью самого React. Да, я согласен, но моей главной целью здесь было показать вам, как работает redux thunk, на более простом примере. Как только вы это поймете, вы можете легко применить этот подход и воспроизвести его в более крупных проектах с некоторыми изменениями.

Теперь, когда вы понимаете, как работает redux thunk, улучшите это приложение еще больше, используйте React Router и создайте отдельную страницу, используйте некоторые другие API, такие как API Reddit, и извлеките некоторые данные и покажите их в красивом чистом пользовательском интерфейсе. Может быть, узнаешь, как можно кэшировать эти запросы. Вы даже можете добавить несколько пользовательских анимаций при раскрытии компонента UserInfo. Как видите, мы можем легко расширить это приложение на более сложные территории, если захотим.

Спасибо, что прочитали эту длинную статью, и я вернусь с другой.

✉️ Подпишитесь на рассылку еженедельно Email Blast 🐦 Подпишитесь на CodeBurst на Twitter , просмотрите 🗺️ Дорожная карта веб-разработчиков на 2018 год и 🕸️ Изучите веб-разработку с полным стеком .