27Oct

iron-1920-1080-wallpaper

Теперь начнем разбираться в том как, мы работаем с данными. Пока, для отображения статей мы использовали денормализированную структуру. Ее видно в файле fixtures.js. В каждой статье есть вся информация о ней, она напоминает древовидную структуру. Подобная структура удобна для чтения, но она превратит вашу жизнь в ад если вы начнете как-то изменять эти данные. Если у вас будет более или менее сложная структура, где эти зависимости будут пересекаться, например, у статьи есть автор у комментария есть автор, у автора есть своя страница. Если хранить это в том виде как это есть сейчас, то когда вы захотите поменять имя этого автора, вам придется просмотреть все места где даже чисто теоретически он может использоваться и заменить эти данные, и скорее всего Вы что-то пропустите. Поэтому, перед тем как сохранять данные в stores их нормализируют. Нужно отдельно хранить сущности комментариев, статей, авторов и.т.п, и отдельно хранить связи (например у статьи есть много комментариев), в виде id.

На клиенте удобно хранить данные в одном месте, к примеру, там где много комментариев, там сразу можно хранить массив с id этих комментариев. Это довольно удобно, так как все манипуляции с нашими данными можно будет делать в одномreducer. Давайте реализуем такую структуру. Сделаем reducer для комментариев, для этого в папке reducer создадим файл comments.js:

import {  } from '../constants'

export default (comments = {}, action) => {
    const { type, payload, response, error } = action

    switch (type) {

    }

    return comments
}

Также мы немного изменим то, как мы храним данные, сейчас мы храним их в виде обычного массива, и это не очень удобно, если мы хотим работать с данными. Нам часто нужно обращаться к конкретному элементу, поэтому будет удобнее хранить данные в виде объектов, ключами в которых выступают id (статьи например), а их значением будет сама статья. Таким образом мы значительно упростим обращение к элементам нашего store.  Давайте все это перестроим и начнем с reducer/articles.js. В articles мы будем уже брать normalizedArticles, изменим import следующим образом:

import { normalizedArticles } from '../fixtures'

Также в reducer/comments.js добавим import:

import { normalizedComments } from '../fixtures'

Продолжим наш урок с использованием библиотеки immutable.js. Установим ее:

npm i immutable --s

У immutable.js есть разные структуры данных, одна из самых часто используемых List, это аналог массива, просто immutable. Map это аналог объекта.OrderedMap– это вариация Mapгде вы сохраняете последовательность в которой были добавлены элементы. И еще есть такой элемент Record, в который позволяет описать вид в котором у Вас находится элемент. Давайте используем  Record и OrderedMap в нашем проекте.  Сделаем следующие  записи в reducer/articles.js:

import { normalizedArticles } from '../fixtures'
import { DELETE_ARTICLE } from '../constants'
import { OrderedMap, Record } from 'immutable'


const Article = Record({
    "id": "",
    "date": "",
    "title": "",
    "text": "",
    "comments": []
})

const defaultArticles = normalizedArticles.reduce((acc, el) => {
    return acc.set(el.id, new Article(el))
}, new OrderedMap({}))

export default (articles = defaultArticles, action) => {
    const { type, payload } = action

    switch (type) {
        case DELETE_ARTICLE:
            return articles.filter(article => article.id != payload.id)
    }
    return articles
}

В переменной defaultArticles мы с Вами идем по массиву normalizedArticles и с помощью метода reduce проходим от первого до последнего элемента  массива, собирая их в какую-то другую структуру, в нашем случает в immutabele объект acc, также здесь есть  el – это элемент к которому мы сейчас обращаемся (первая статья, вторая статья и т.д.). И начальное значение acc, то с которого мы начинаем – new OrderedMap({})).  Возвращаем мы с Вами:

acc.set(el.id, new Article(el))

В константе  const Article вы описываете то, какого вида у Вас статьи. В нашем случае мы указываем default значения для статей. Все записи будут храниться в таком виде. В данном случае можно было воспользоваться и обычными объектами и методом mapи тогда нечего особенно для Вас не поменяется. Но Record придуман именно для подобных записей. У Вас появляется гарантированная структура Ваших данных (статей) и она будет всегда выдержана . Также будет удобнее обращаться к immutabele объекту article, к примеру при использовании простого объекта будет выглядеть так:
article.get('title'), если мы используем Record,  у нас уже есть готовый getter и мы сможем просто обращаться:article.title.

Далее нужно будет немного поменять наш API, перейдем в containers/Filters.js и сделаем следующие изменения:

export default connect(state => {
    const { articles, filters } = state
    return {
        articles: articles.valueSeq(),
        filters
    }
}, { changeFilters

Раньше мы рассчитывали что будем работать с массивом, а сейчас мы получаем объект. Поэтому мы преобразуем его в connect. Для того чтобы превратить структуру  OrderedMapв массив  List мы вызываем метод valueSeq() таким образом у нас получится просто массив статей.

Также у нас могут быть проблемы в select, т.к. мы ожидали что в нем у нас приходит массив, а теперь мы получаем custom structure.  Чтобы ошибок не произошло необходимо пойти в атрибуту options превратив их в toJS():

                <Select
                    options = {options.toJS()}
                    multi = {true}
                    value = {filters.selectedArticles}
                    onChange = {this.handleSelectChange}
                />

Также необходимо будет исправить containers/Articles.js:

function filterArticles(articles, { from, to, selectedArticles }) {
    return articles.valueSeq()

Почему мы вызываем valueSeq()? Потому, что articles – это объект (ключ : значение), а мы хотим достать из него значения и поместить их в массив. Аналогично этому есть также keySeq , для того чтобы достать ключи. Дальше преобразовывать ничего не надо, так как React прекрасно понимает immutable.js, и его структуры. Поэтому не надо переводить их в нативные JS структуры.

Код урока вы можете найти в нашем репозитории.

to_be_continued

We are looking forward to meeting you on our website soshace.com

Code Review

Code Review проводиться в назначенных парах не мене 2 месяцев с даты формирования пары для лучшего понимания проекта поверяющими сторонами.

Таблица результатов ревью здесь.

Советы по Code Review:

1. Уроки Node.js .Модули. Часть 1.

Давайте создадим Ваш первый проект с Node.js. Нашей основной целью будет знакомство с модулями – способом который Node предлагает для организации проекта.

Установите Node на свой компьютер.

https://nodejs.org

Уроки React. Урок 2, Домашнее задание.

Давайте пробежимся по нашему домашнему заданию. Смысл использования React это создание компонентов из вашего функционала, т.е. дробление приложение на маленькие независимые части. В нашем случае комментарии нужно сделать комментарии отдельным компонентами. Также хорошей практикой считается иметь как можно больше stateless компонентов. К примеру в нашем случае это файл comment.js.

Leave a Reply