react-logo_13_2

Теперь давайте это вызовем в containers/Articles.js , добавив такую запись вызывая action creater:

import { loadAllArticles } from '../AC/articles'

class Articles extends Component {
    static propTypes = {

    };

    componentDidMount() {
        this.props.loadAllArticles()
    }

А ниже в connect мы его обернем :

export default connect(({ articles, filters }) => {
    return {
        articles: filterArticles(articles, filters)
    }
}, {
    loadAllArticles
})(Articles)

А далее вызовем в  componentDidMount().

Также в reducer/articles.js мы  уберем defaultArticles которые мы с Вами создавали:

const defaultArticles = new OrderedMap({})

Не забудем подключить в import объект OrderedMap:

import { Record, OrderedMap } from 'immutable'

Теперь нужно подключить наш middleware в нашем store.

Делаем import:

import api from '../middlewares/api'

И добавляем ее в ряд с другими middleware например после randomID:

const enhancer = compose(
    applyMiddleware(dumbMiddleware, randomId, api, logger),
    window.devToolsExtension ? window.devToolsExtension() : f => f
)

Теперь если перезапустить приложение в console можно увидеть что происходит LOAD_ALL_ARTICLES_SUCCESS

Давайте добавим setTimeout для симуляции некого далекого API, добавим это в middlewares/api.js:

   setTimeout(() => {
        $.get(callAPI)
            .done(response => next({type: type + SUCCESS, response, ...rest}))
            .fail(error => next({type: type + FAIL, error, ...rest}))
    }, 1000)
}

Теперь, если вы зайдет в console и перезагрузите наше приложение, у Вас произойдут действия  START и через секунду SUCCESS.

Теперь нам осталось научить наши reducers обращаться с новой логикой. Перейдем в reducer/articles.js.  Здесь нам уже недостаточно просто иметь articles в виде набора статей, поскольку наше приложение развивается, становиться более сложным, и появляется необходимость иметь информацию о статусе загрузки статей.

Подключим Map а также immutable массив  List из immutable.js:

import { Record, OrderedMap, Map, List } from 'immutable'

Опишем начальное состояние нашего reducer  , добавив следующую запись:

const defaultState = new Map({
    loading: false,
    loaded: false,
    errors: new List([]),
    entities: defaultArticles
})

Добавив сюда сами статьи у нас получилась структура, которую мы сможем переиспользовать от одного reducer к другому. Т.е. entities
у нас будут как статьи так и комментарии. Наш код ниже тоже  претерпит изменения:

export default (state = defaultState, action) => {
    const { type, payload, response, randomId } = action

    switch (type) {


        case ADD_COMMENT:
            return state.updateIn(['entities' ,payload.articleId, 'comments'], comments => comments.concat(randomId))

        case LOAD_ALL_ARTICLES + START:
            return state.set('loading', true)

        case LOAD_ALL_ARTICLES + SUCCESS:
            return state
                .set('loading', false)
                .set('entities', recordsFromArray(Article, response))
                //return state.update('entities', entities => entities.merge(recordsFromArray(Article, response)))

    }
   
    return state
}

Обратите Ваше внимание на закомментированную строку. Эта запись описывает подход как можно по-другому с помощью методов update и  merge из immutable.js загрузить наши статьи. В этом случаем мы  делаем обновление списка наших статей. Когда у нас приходит LOAD_ALL_ARTICLES + SUCCESS  мы берем старые entities  (если они у нас были) и делаем merge с новыми. По умолчанию, процесс добавления статей будет реализован нами c помощью set  – т.е. просто полным обновлением списка. Мы добавили .set('loading', ...), для того чтобы можно было добавить loader при загрузке наших статей.

Read More:  Уроки React. Урок 4. Домашнее Задание.

Идем дальше, теперь нам нужно переписать логику того как мы получаем данные в filterArticles в containers/Articles.jsа также добавить loader в наш UI:

    render() {
        const { articles, loading } = this.props
        if (loading) return <h1>Loading...</h1>
        return <ArticleList articles = {articles} />
    }
}

export default connect(({ articles, filters }) => {
    return {
        loading: articles.get('loading'),
        articles: filterArticles(articles.get('entities'), filters)
    }
}, {
    loadAllArticles
})(Articles)

Мы добавили индикатор в export default), а  в render простенький loader. (когда мы закончим, до загрузки статей будет появлятся соответствующая надпись “Loading”).
В immutable.js вы должны явно писать ваше обращение  для того чтобы получить данные articles.get('entities'). Когда мы использовали immutable object Record мы могли избежать такого рода обращения, т.к. все происходило “под капотом” и getters, setters, создавались внутри, как в случае с const Article в reducer/articles.js.
Продолжим наши преобразования и изменим  reducer/articles.js  следующим образом:

import { DELETE_ARTICLE, ADD_COMMENT, LOAD_ALL_ARTICLES, START, SUCCESS } from '../constants'
import { Record, OrderedMap, Map, List } from 'immutable'
import { recordsFromArray } from './utils'

ошибки мы с Вами пока обрабатывать пока не будем. Запись про importnormalizedArticles нам здесь больше не понадобиться. Поменяем нашу константу defaultArticles :

const defaultArticles = recordsFromArray(Article, [])

И конечно же return в конце файла:

return state

Теперь все готово, можно проверять! Код нашего урока доступен по этой ссылке. До скорых встреч, дальше еще очень много интересного, увидимся!

react-boilerplate

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

Share.
Leave A Reply