31Oct

react_11_1

На предыдущем уроке мы научились более удобным способом писать reducers используя удобные API для добавления/удаления элементов, не беспокоясь о том, что мы что-то изменим по дороге.

Теперь если мы с Вами посмотрим на наше приложение и откроем какую-нибудь статью, то увидим в console warnning. Наши propTypes предупреждают нас о наличии проблемы, еще до того момента как мы до нее доберемся. Это огромный плюс – то что мы их написали. О чем говорит этот warnning ? Он говорит о том что мы ожидали получить в Comment объект с комментарием, а сейчас передаем туда число. И действительно если открыть комментарии, то их там не будет. Для того чтобы они появились нам нужно пойти в часть storeкоторая отвечает за commentsи достать оттуда необходимые комментарии. Аналогично тому, что мы сделали с Вами со статьями, нам предстоит сделать с комментариями.

Изменим reducer/comments.js следующим образом:

import {  } from '../constants'
import { normalizedComments } from '../fixtures'
import { Record } from 'immutable'
import { recordsFromArray } from './utils'

const Comment = Record({
    "id": null,
    "user": "",
    "text": ""
})

const defaultComments = recordsFromArray(Comment, normalizedComments)

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

    switch (type) {

    }

    return comments
}

А также создадим файл reducer/utils.jsи вынесем туда часть нашей логики, которую будет удобно переиспользовать в дальнейшем, а не просто ее копировать:

import { OrderedMap } from 'immutable'

export function recordsFromArray(RecordType, array) {
    return array.reduce((acc, el) => {
        return acc.set(el.id, new RecordType(el))
    }, new OrderedMap({}))
}

Здесь наши с помощью recordsFromArray данные превращаются в immutable.js структуру.

Также изменить reducer/articles.js:

import { normalizedArticles } from '../fixtures'
import { DELETE_ARTICLE } from '../constants'
import { Record } from 'immutable'
import { recordsFromArray } from './utils'

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

const defaultArticles = recordsFromArray(Article, normalizedArticles)

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

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

И последний шаг изменим import в reducer/index.js:

import articles from './articles'
import comments from './comments'
import counter from './counter'
import filters from './filters'
import { combineReducers } from 'redux'

export default combineReducers({
    count: counter,
    articles, filters, comments
})

Теперь нам нужно эти комментарии как-то достать, раньше они были внутри статей, а теперь там есть только ссылки. Чтобы это сделать мы пойдем в то место, где мы их использовали, а именно в components/Article/index.js. Мы должны решить, будем мы получать их в commentList или же в самом компоненте статьи. Забегая вперед сейчас мы отдадим предпочтение commentList . Нам сейчас нужно обернуть наш компонент в connect и достать по id комментариев сами комментарии. Мы можем это сделать в компоненте Article/index.js, здесь у нас уже есть connect и мы его можем использовать, чтобы достать comments из store. А можем это сделать в commentList
уже здесь получив id просто достав их из store. Зайдем в commentListи сделаем import:

import { connect } from 'react-redux'

Далее в самом низу изменим  export default:

export default connect((state, { comments }) => {
    return {
        commentObjects: comments.map(id => state.comments.get(id))
    }
})(toggleOpen(CommentList))

Помимо аргумента state у Вашего store есть второй props, которые и так приходили в Ваш компонент. А приходит в props у нас comments. Давайте это используем. Чтобы не путаться назовем то что у нас будет в return – commentObjects, подчеркивая, что это уже объект. Здесь мы пройдемся по  массиву комментариев и с помощью  immutable map и по id будем доставать из state наши комментарии (т.е. records комментариев).

В render мы уже работаем с нашим объектом, поэтому код станет выглядеть так:

 render() {
        const { commentObjects, isOpen, toggleOpen } = this.props

Также в reducer/articles.js изменим фильтрацию, так как нам она больше не нужна в том виде в котором она была написана.

return articles.delete(payload.id)

Мы просто описываем какую статью нужно удалить из объекта. Если нужно добавить вы используете set()если обновить то update().

articles.set()
articles.update()

Это пригодиться в будущем домашнем задании. Также Immutable.js прекрасно работает с глубокой вложенностью. Если вдруг Вам нужно обновить комментарии, которые вложены в статью которые, вложены в объект со всеми статьями, который возможно вложен в еще какой-нибудь объект, который помимо всего хранит другие всевозможные данные, то вы замучаетесь писать функции-обертки. Для таких случаев в Immutable.js есть:

articles.updateIn([id, 'comments'], comments => ...)

Проверяем, все прекрасно работает!

Мы с Вами уже нормализировали данные и храним отдельно статьи и комментарии, это пойдет на пользу когда мы будем читать данные с API так как очень часто REST API отдают данные в таком виде. Т.е. end points отвечают за какие-нибудь ресурсы, например за статью или за комментарий и далеко не всегда у вас есть API который сразу готов отдать древовидную структуру статьи со всеми комментариями и.т.д. Такую проблему решает GraphQL например. Relay и GraphQL это React структура – то что Facebook использует у себя для fetching’а данных, но это уже довольно сложные темы. Но обычно наш API будет в таком виде:

http://localhost:8080/api/article

Отдельно будет API для комментариев:
http://localhost:8080/api/comment

И нужно будет заставить их работать вместе (“подружить” их). Чем мы в дальнейшем и займемся, получая все статьи, комментарии из реального API.

Далее мы продолжим знакомиться с Redux API  и посмотрим что же такое Middleware. Все что мы до этого момента делали прекрасно описывалось чистыми функциями и в принципе в Redux все стоит делать чистыми функциями, это и action creators и reducers. Они получают на входе старые данные и action и возвращают на выходе новый объект с новыми статьями, не меняя ничего во “внешнем мире”.

С другой стороны в реальной жизни не все можно описать чистыми функциями, иногда нам нужны side-effects – это любое обращение к API, Logging, Reporting и.т.д. Все это вынесено в middleware . Это то что находиться между тем как вы произвели dispatch над actionи тем как это попало в Ваши reducers.

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

 

Уроки React. Урок 6.

Давайте продолжим наш разговор об инфраструктуре вокруг React. Но для начала давайте немного изменим нашу структуру и поместим компонент Article в отдельную директорию Articel,создадим ее для начала. Имя нашего компонента на Index.js и добавим в него следующий код:

12. Уроки Node.js . Документация Http Модуля.

В дальнейшем мы будем часто обращаться к модулю http, поэтому сейчас небольшая экскурсия по его документации, что в ней есть и где это искать.
Сейчас модуль http совмещает в себе два функционала. Первый – это функционал сервера. http.createServer создает новый объект класса Server. Если передан обработчик, то он ставится на событие request. Второй функционал – это createClient.

4. Уроки Node.js. Структура Пакета NPM

Продолжаем наш разговор об NPM.Для того чтобы посмотреть на реальный package.json поставим модуль express. Введем в консоли:

npm i [email protected]

Этим модулем мы будем еще пользоваться в будущем, а сейчас мы просто ставим этот внешний модуль и посмотрим на его package.json, как он выглядит. Обнаружим там массу всего интересного.

Мы кратко пройдемся по некоторым особенностям package.json пока что в общих чертах, в дальнейшем, когда мы будем делать конкретные вещи, то используем это для решения конкретных задач. Итак, поля.

3 Replies to “Уроки React. Урок 11. Pt.1.”

  1. Здравствуйте! А нельзя ли ссылку на весь файл CommentList.js, ибо с правками, которые вы даете комментариев не видно. Как вот здесь передать text:

    const listComments = commentObjects.map((comment) => {
    return(

    )
    });

    1. Добрый день! Вот ссылка на файл в репозитории:

      https://github.com/soshace/react_lessons/blob/lesson_11/src/components/CommentList.js

      Прочтите вторую часть 11 урока обязательно, тогда должно стать все понятно!

      1. Спасибо, уже нашел проблему. Сам натупил: сделал опечатку))) Зато глубже разобрался в механизмах immutable и логике приложения. Ваши уроки, как по мне, довольно сложные, но как говорил Омар Хаям: “Никогда не сдавайся! Если тебе тяжело — значит ты на верном пути!

Leave a Reply