如何在 Redux 和 React.js 中的异步多个请求上使用 Loader



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

它看起来像这样:

当我的 axios 请求完成时,我的化简器添加了 isFetching 标志(存储已更新(:

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 请求。 在这种情况下,您使用哪种策略?

谢谢!

每当有多个获取请求,甚至多个操作表明正在发生异步事件并需要存储在状态的一部分中时,我都会使用计数器:

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

下面请以 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)

最新更新