git clonecd client && npm installcd server && npm installcd stub && npm install
cd client && npm start- ready app in dev modecd stub && npm start- app stubcd server && npm start- web server. generates random data
Directory client contains a fully implemented application. On the other hand, directory stub contains partially implemented application. You can improve your skill by implementing it by yourself.
If you have some problems with implementing you can check instruction below. I write down every step during the implementation.
Also in the implementation branch you can find implemented stub directory and commits for every part of instruction.
Before starting the implementation I recommend to see these diagrams...
I. Запустить счетчик температуры (сейчас статика)
- Смотрим
index.jsx- В компонент Provider мы передаем общий state приложения
appStore - Переходим в файл
app.store.jsиз которого импортируетсяstore
- В компонент Provider мы передаем общий state приложения
- Смотрим
app.store.js- В данном файле мы видим хинт (в виде комментария), который намекает нам, что нужно установить middleware для redux state.
- Для этого импортируем
createEpicMiddlewareфункцию из библиотекиredux-observable - Библиотека позволяет использовать epics в качестве middleware, поэтому нам необходимо подключить главный epic
rootEpic - Делается это по аналогии с
rootReducer - Создаём новый
epicsMiddlewareпри помощиcreateEpicMiddleware - Передаем
epicsMiddlewareвapplyMiddleware
- Сделали, получили ошибку
Module not found: Can't resolve './temperature/epics' in 'stub/src’- Это ошибка означает, что у нас отсутсвует epic для компонента
temperature - Создадим файл
epics.jsв директории./temperatureпо аналогии с остальными директориями - Для начала импортируем вспомогательную функцию
FetchEpicиз файла../common/epic-creators.js - Затем импортируем константы
FETCH,FETCH_DONE,FETCH_FAILEDиз соответствующего данному компоненту редьюсера - Импортируем адаптер
- Затем экспортируем переменную
temperatureFetchEpic, которая содержит в себе возвращаемый результат функцииFetchEpicс переданными константами типов и функцией исполнения
- Это ошибка означает, что у нас отсутсвует epic для компонента
- Сделали, получили ошибку
Module not found: Can't resolve '../common/epic-creators'- На самом деле сейчас у нас нет в проекте файла
epic-creators, который содержит вспомогательную функциюFetchEpic. - Добавим его… (тут можно и расписать подробнее :))
- На самом деле сейчас у нас нет в проекте файла
- Добавили, получили ошибку
'../conditions/reducer' does not contain an export named 'CALC_CONDITIONS'- Просто добавим строчку
export const CALC_CONDITIONS = 'summary.calcConditions';в качестве заглушки
- Просто добавим строчку
- Добавили, ошибок нет, но данные не обновляются.
- Идем в файл
app.reducer.jsи импортируемsyncReducer - Затем добавляем его в
rootReducer - Затем идем в
app.component.jsxи импортируемSYNC_STARTиAction - При componentDidMount диспатчим
Action(SYNC_START)
- Идем в файл
- Сделали, получили ошибку в
conditions/epics.jsв функцииgetValueFromState- Причина ошибки простая, функция опирается еще на не существующие записи в store precipitation, humidity и т.д.
- Необходимо просто исключить ненужные на данном этапе эпики из
rootEpic - Закоментируем все строчки, кроме нужных нам
temperatureFetchEpic,syncStartEpic,syncEpic
- Заходим на страницу. Успех! Счетчик температуры обновляется!
- Коммит стэйбл вершион!
II. Запустить счетчик ветра (сейчас его нет)
- Добавим
windReducerвapp.reducer.js - Расскоментируем
windSpeedFetchEpic,windDirectionFetchEpicвapp.epics.js - Откроем файл
app.component.jsxи добавим компонентDashboardPanelдля отображения скорости ветра (по аналогии с температурой) - В таких props как
errorиloadingзаменим'temperature'на'wind' this.getValue('temperature')заменим наthis.getValue('wind.speed’). Так как ветер имеет как скорость так и направление- Осталось исправить функцию
getValue, чтобы она могла принимать вложенные поля переменной... - Счетчик обновляется!
- Теперь добавим функцию
getWindDirectionIconдля определения иконки ветра в зависимости от направления - И передадим соответствующую иконку в props компонента
DashboardPanel - Иконка направления обновляется!
III. Запустить счетчик влажности (humidity)
- Добавим
humidityReducerвapp.reducer.js - Расскоментируем
humidityFetchEpicвapp.epics.js - Откроем файл
app.component.jsxи добавим компонентDashboardPanelдля отображения влажности (по аналогии с температурой) - Заменим параметры
temperatureнаwind - Успех! Влажность обновляется!
- Коммит!
IV. Запустить учет conditions в верхнем компоненте на странице
- Идем в файл
conditions/reducer.js- Видим, что в данный момент reducer всегда возвращает прежний
stateи начальное состояние равноsnow - Устанавливаем начальное состояние равное
na - Объявляем константу
CALC_CONDITIONS - Пишем обработчик поступающих в Reducer событий (switch - case)
- Для события
CALC_CONDITIONSнапишем 2 вспомогательные функции:calcConditionsActionHandlerиcomposeConditions calcConditionsActionHandlerвызывается при срабатывании событияCALC_CONDITIONSи возвращает новыйstatecomposeConditonsиспользуется для расчета нового состояния на основе погодных данных
- Видим, что в данный момент reducer всегда возвращает прежний
- Далее идем в файл
app.epics.jsи добавляем эпикcalcConditionsEpic - Так как для расчета состояния используется precipitation необходимо включить также соответсвующий epic и reducer
- Готово! Состояние обновляется!
- Коммит!
V. Подключить статистику
- Подключаем
statsReducerвrootReducer - Раскомментируем необходимые для статистики эпики в
rootEpic - Открываем файл
app.component.jsx- Создаем специальную функцию
getStatsFor(type)которая возвращает статистику для определенного типа событий - Теперь нам необходимо передать props
statsValuesв каждый из компонентов
- Создаем специальную функцию
- Затем необходимо создать новый компонент
StatsTableкаждый и использовать его внутриdashboard-panelкомпонента для отображения статистики - Сделали, получаем ошибку
«Cannot read property 'daily' of undefined». Это возникаем из-за того, что мы передали статистику только в 1 компонент (temperature), а остальные получают undefined. - Для решения в файле
stats-table.component.jsxв методеgetValueизначально проверяем values на undefined и возвращаем'--'если это так. - Отлично! Статистика для температуры считается.
- Подключим остальные компоненты (ветер и влажность)
- Ура! Все компоненты ведут статистику!
- Коммит!
VI. При обновлении статистики было замечено, что не считается общая средняя температура
- Анализируем функцию
TotalStatsEpic - Замечаем, что функцию считается с ошибкой для temperature, потому что в состоянии temperature отсутсвует
tick - Анализируем редьюсер для temperature и понимаем, что он использует вложенные редьюсеры которые находятся в этом же файле.
- Заменяем их на аналогичные общие функции, которые успешно используются в остальных компонентах.
- Общая статистика работает!
- Коммит!

