如何在Redux和React.js中使用Loader on async multiple request

时间:2018-06-03 12:44:20

标签: reactjs redux react-redux

我正在尝试在尚未提取数据时设置Loader。如果数据只上传一个,这种情况很容易(逻辑在这里:设置一个标志isFetching为true,当从redux接收时将其设置为false)。但我的情况有点不同。我想多次获取我的数据来更新我的日历组件。所有这些都是通过带有axios包的redux完成的。

看起来像是:

我的reducer在我的axios请求完成后添加isFetching标志(商店已更新):

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);

组件看起来像那样:

{{1}}

因此axios请求会多次出现新值。 在这种情况下你使用什么样的策略?

谢谢!

2 个答案:

答案 0 :(得分:0)

每当有多个抓取请求,或者甚至多个动作指示异步发生并且需要存储在状态的一部分时,我使用计数器:

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;
    }
}

然后,您只需检查mapstatetoprops中的fetchCount > 0即可。

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

答案 1 :(得分:-1)

请以下面的例子为例,Redux-thunk样式动作用于包装多个axios请求并将它们全部发送。

&#13;
&#13;
//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)
&#13;
&#13;
&#13;