Благодаря такой схеме, в reducer'e мы сможем реализовать подобное:
switch(тип_действия) case ТИП_ДЕЙСТВИЯ_ЗАПРОС: покажи preloader case ТИП_ДЕЙСТВИЯ_УСПЕШНО: скрой preloader, покажи данные case ТИП_ДЕЙСТВИЯ_НЕУДАЧНО: скрой preloader, покажи ошибку
Как нам известно, действие - это простой объект, который возвращается функцией его создающей (action creator).
Было бы неплохо иметь возможность возвращать не простой объект, а функцию, внутри которой иметь доступ к методу dispatch, чтобы можно было диспатчить события в момент, когда они совершились. Псевдокод, мог бы выглядеть так:
Но вот незадача, actions - это простой объект, и если action creator возвращает не простой объект, а функцию, то это как-то... Подождите! Ведь это именно то, что нам нужно: Если action creator возвращает не простой объект, а функцию - выполни ее, иначе если это простой объект ... тадам, передай дальше. Более того, мы знаем, что в цепочке middleware у нас как раз есть доступный метод dispatch! И еще бонусом getState.
Отлично, мы только что поняли, что нам нужен еще один усилитель. Такой усилитель уже написан, причем код его невероятно прост, я даже приведу его здесь:
exportconstGET_PHOTOS_REQUEST='GET_PHOTOS_REQUEST'exportconstGET_PHOTOS_SUCCESS='GET_PHOTOS_SUCCESS'exportfunctiongetPhotos(year) {return dispatch => {// экшен с типом REQUEST (запрос начался)// диспатчится сразу, как будто-бы перед реальным запросомdispatch({ type:GET_PHOTOS_REQUEST, payload: year, })// а экшен внутри setTimeout// диспатчится через секунду// как будто-бы в это время// наши данные загружались из сетиsetTimeout(() => {dispatch({ type:GET_PHOTOS_SUCCESS, payload: [1,2,3,4,5], }) },1000) }}
Изменим reducer: src/reducers/page.js
import { GET_PHOTOS_REQUEST, GET_PHOTOS_SUCCESS } from'../actions/PageActions'constinitialState= { year:2018, photos: [], isFetching:false,// изначально статус загрузки - ложь// так как он станет true, когда запрос начнет выполнение}exportfunctionpageReducer(state = initialState, action) {switch (action.type) {caseGET_PHOTOS_REQUEST:return { ...state, year:action.payload, isFetching:true }caseGET_PHOTOS_SUCCESS:return { ...state, photos:action.payload, isFetching:false }default:return state }}
У нас готова логика для обновления состояния (и интерфейса, разумеется). Осталось поправить отображение.
Так как мы переписали и переименовали функцию (setYear -> getPhotos):
Когда будете проверять работу в браузере, обратите внимание на логгер. Он все так же работает и информативен.
Пока мы писали код для асинхронного запроса, мы НЕ нарушили главные принципы redux-приложения:
Мы всегда возвращали новое состояние (новый объект, смотрите src/reducers/page.js)
Мы строго следовали однонаправленному потоку данных в приложении: юзер кликнул - возникло действие - редьюсер изменил - компонент отобразил.
Итого: вы можете сами дописать наше приложение, чтобы оно взаимодействовало с VK, так как все что нужно, это добавить реальный асинхронный запрос (точнее парочку - для логина, и для получения фото). Для этого придется почитать документацию по работе с VK API.
Для тех, кто хочет добить пример поскорее - следующая глава, в которой мы загрузим таки реальные фото из вашего профиля VK.