Как построить архитектуру React + Redux приложения?

Познаю мир фронтенда вместе с React, Redux и компанией.

Есть несколько компонентов. Хочу, чтобы они загружались асинхронно друг от друга, даже когда они вложены. Cделал примерно так:

- в каждый компонент пробрасывается весь store приложения;
- если данных этого компонента нет в store, то в constructor() вызывается action для получения данных;
- в render() показываем данные, если они есть, либо заглушку "загрузка".

По отдельности все прекрасно. Когда пытаюсь скомпоновать несколько таких компонентов, получаю warning:

warning.js:45 Warning: setState(...): Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state.

Как правильно построить архитектуру React+Redux приложения так, чтобы дочерние компоненты загружались асинхронно с родительскими.
  • Вопрос задан
  • 918 просмотров
Решения вопроса 1
Amazing-Space-Invader
@Amazing-Space-Invader
веб-хипстер
Привет! Вот небольшой листинг кода, надеюсь, что он поможет тебе разобраться самостоятельно.
+ вот неплохая статья о redux

actions/constants.js
export const LIST_AD_REQUEST = 'LIST_AD_REQUEST';
export const LIST_AD_SUCCESS = 'LIST_AD_SUCCESS';
export const LIST_AD_FAILURE = 'LIST_AD_FAILURE';


actions/listAdActions.js
import request from 'superagent'
import Auth from '../modules/Auth'

import { adUrl,
    LIST_AD_REQUEST, LIST_AD_SUCCESS, LIST_AD_FAILURE } from './constants'

export function listAd() {
    return (dispatch) => {
        dispatch(listAdRequest());

        const userId = Auth.getUserId();
        const params = `?author=${userId}&list=true`;

        return request
            .get(adUrl + params)
            .set('Accept', 'application/json')
            .set('Authorization', Auth.getToken())
            .end((err, res) => {
                if (err) {
                    dispatch(listAdFailure(err));
                } else {
                    dispatch(listAdSuccess(res.body));
                }
            });
    }
}

function listAdRequest() {
    return { type: LIST_AD_REQUEST }
}

function listAdSuccess(ads) {
    return { type: LIST_AD_SUCCESS, ads }
}

function listAdFailure() {
    return { type: LIST_AD_FAILURE }
}


reducers/ads.js
import {
    LIST_AD_REQUEST, LIST_AD_SUCCESS, LIST_AD_FAILURE
} from '../actions/constants'

const ads = (state = [], action) => {
    switch (action.type) {
        case LIST_AD_SUCCESS:
            return action.ads;

        default:
            return state;
    }
};


reducers/index.js
import ads from './ad'

export default Object.assign({}, ads);


containers/ListAds/ListAds.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { listAd } from '../../actions/ListAdActions'

class ListAd extends Component {
    componentDidMount() {
        this.props.dispatch(listAd());
    }

    render() {
        const { ads } = this.props;

        return (
            <div>
                <div className={ s.content }>

                    { 
                        ads.map((ad, i) =>
                            <div className={ s.ad } key={ i }>
                                <h3>
                                    <Link to={ 'list-ad/single-ad/' + ad.id }>{ ad.name }</Link>
                                </h3>
                                <small>{ ad.status }</small>

                                <ul>
                                    <li><b>Дата начала</b>: { ad.start_date }</li>
                                    <li><b>Дата конца</b>: { ad.stop_date }</li>
                                    <li><b>Бюджет</b>: { ad.budget }</li>
                                </ul>
                            </div>
                        )
                    }

                </div>
            </div>
        )
    }
}

export default connect(state => ({ ads: state.ads, user: state.user }))(ListAd)


Также можно использовать акшон getAdsIfNeeded() - суть в том, что если в state есть ads, то реквест к апи не произойдет.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы