Как использовать Loader для асинхронного множественного запроса в Redux и React.js - PullRequest
0 голосов
/ 03 июня 2018

Я пытаюсь установить Loader, когда данные еще не получены.Этот сценарий будет легким, если данные будут загружены только по одному (логика здесь: установите флаг isFetching в значение true, при получении из избыточного числа установите его в значение false).Но мой сценарий немного другой.Я хотел бы получить свои данные несколько раз, чтобы обновить компонент календаря.Все делается с помощью пакета AXIOS.

Это выглядит так:

Мой редуктор добавляет флаг isFetching, когда мой запрос axios выполнен (хранилище обновлено):

import { ACTIVE_MONTH } from "../actions/types";

export default function(state = null, action){
    switch(action.type){
        case ACTIVE_MONTH:
            return Object.assign({}, state, {
                isFetching: false,
                fullyBooked: action.payload
            })
        default:
            return state;
    }
}

И компонент выглядит так:

import React, { Component } from 'react';
import Calendar from 'react-calendar';
import ChooseHour from './ChooseHour';
import { connect } from 'react-redux';
import * as actions from '../actions';

class Calendario extends Component {
    state = { showHours: false, disabledDates: null}

    componentDidMount() {
        const { chosenRoom } = this.props;
        const date = new Date();
        const reqMonth = date.getMonth() + 1;
        const reqYear = date.getFullYear();
        this.props.activeMonthYearToPass({reqMonth, reqYear, chosenRoom});
    }

    onChange = date => this.setState({ date }, () => {
            const { chosenRoom, isBirthday } = this.props;
            const year = date.getFullYear();
            const month = date.getMonth() + 1;
            const day = date.getDate();
            const fullDate = `${year}/${month}/${day}`;
            const roomAndDayObj = {fullDate, chosenRoom, isBirthday};
            this.props.sendRoomAndDay(roomAndDayObj); 
        }
    );

    onClickDay(e) {
        const { chosenRoom } = this.props;
        !chosenRoom ? this.setState({ errorMsg: "Wybierz pokój", showHours: false}) :
        this.setState({ showHours: true, errorMsg:'' });
    } 

    passActiveDate(activeDate) {
        const { chosenRoom } = this.props;
        const reqMonth = activeDate.getMonth() + 1;
        const reqYear = activeDate.getFullYear();
        this.setState({ pending: true},
            () => this.props.activeMonthYearToPass({reqMonth, reqYear, chosenRoom})
        );
        this.props.passDateDetails({reqMonth, reqYear});
    }

    render() { 
        const { fullyBookedDays, isBirthday } = this.props;
        const { errorMsg, pending } = this.state;
        return ( 
        <div>
            <div className="calendarsCont">
                    <Calendar
                        onChange={this.onChange}
                        onClickDay={(e) => this.onClickDay(e)}
                        onActiveDateChange={({ activeStartDate }) => this.passActiveDate(activeStartDate)}
                        value={this.state.date}
                        locale="pl-PL"
                        tileDisabled={({date, view}) =>
                            (view === 'month') && 
                            fullyBookedDays && fullyBookedDays.fullyBooked.some(item =>
                            date.getFullYear() === new Date(item).getFullYear() &&
                            date.getMonth() === new Date(item).getMonth() -1 &&
                            date.getDate() === new Date(item).getDate()
                            )}
                    /> 
                }
            </div> 
            <p style={{color: 'red'}}>{errorMsg}</p>
            <div>
                {this.state.showHours ? 
                    <ChooseHour chosenDay={this.state.date} chosenRoom={this.props.chosenRoom} isBirthday={isBirthday}/> : 
                null}
            </div>
        </div>
        )
    }
}

function mapStateToProps({fullyBookedDays}){
    return {
        fullyBookedDays,
    }
}

export default connect (mapStateToProps, actions)(Calendario);

Таким образом, новые значения будут приходить много раз из запроса axios.Какую стратегию вы используете в этом случае?

СПАСИБО!

Ответы [ 2 ]

0 голосов
/ 03 июня 2018

Пожалуйста, возьмите в качестве примера приведенное ниже действие в стиле Redux-thunk, чтобы обернуть несколько запросов axios и отправить их все.

//axios call2
function getData1() {
  return axios.get('/data1');
}

//axios call2
function getData2() {
  return axios.get('/data2');
}

//redux-thunk action creator
function getFullData() {
  return (dispatch, getState) => {
    axios.all([getData1(), getData2()])
  .then(axios.spread(function (acct, perms) {
    //call normal action creator
    dispatch(fetchData1())
    dispatch(fetchData2())
  }));
   
  };
}

//normal actioncreator
function fetchData1(data)
{
  return {type: "FETCH_DATA1", payload: data}
}

//normal actioncreator
function fetchData2(data)
{
  return {type: "FETCH_DATA2", payload: data}
}



//reducer1:
function reducer1 (state = defaultedState ,action){
return Object.assign({},{...state, data: action.payload,  isFetching: false} )
}

//reducer2:
function reducer2 (state = defaultedState ,action){
  return Object.assign({},{...state, data: action.payload,  isFetching: false} )
}

//component:
mapStateToProps = function(state){
   return {
     data1: state.data1.data,
     data2: state.data2.data,
     isFetching1: state.data1.isFetching,
     isFetching2: state.data2.isFetching
   }
}

import React, { Component } from "react";
class MyComponent extends Component{
render(){
    return (!data1 && isFetching1) || (!data2 && isFetching2) ? <Loading> : <DataComponent>

}
}

connect(mapStateToProps)(MyComponent)
0 голосов
/ 03 июня 2018

Всякий раз, когда есть несколько запросов на выборку или даже несколько действий, которые указывают на то, что происходит что-то асинхронное и должно быть сохранено в части состояния, я использую счетчик:

export default function(state = {fetchCount: 0}, action){
    switch(action.type){
        case FETCHING_THING:
            return Object.assign({}, state, {
                fetchCount: state.fetchCount + 1
            })
        case FETCHING_THING_DONE:
            return Object.assign({}, state, {
                fetchCount: state.fetchCount - 1,
                fullyBooked: action.payload
            }
        default:
            return state;
    }
}

Тогда вы можете простоотметьте fetchCount > 0 в вашем maptatetoprops.

function mapStateToProps({fullyBookedDays, fetchCount}){
    return {
        fullyBookedDays,
        isLoading: fetchCount > 0
    }
}
...