我有一个React-Redux应用程序,并希望使用axios进行并发API GET请求。我将url作为参数传递给动作。我怎样才能实现它?它是一个UI组件,当单击BU并单击BU时,它具有与API不同的数据。
组件:
import React, { PropTypes, Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { getParallelData } from '../../actions/index';
class BUBGContainer extends Component {
componentDidMount() {
this.props.getParallelData('https://localhost:3001/reports/bu-list');
this.props.getParallelData('https://localhost:3001/reports/bg-list');
}
updateTabs(i) {
if (i === 1) {
this.props.bgTab = true;
this.props.buTab = false;
} else {
this.props.bgTab = false;
this.props.buTab = true;
}
}
render() {
return (
<div className="col-md-3">
<label htmlFor="bu-bg-select">BU/BG:</label>
<ul id="bu-bg-select-tabs" className="nav nav-tabs">
<li role="presentation" className={ 'active' } onClick={ this.updateTabs(0) }><a>BU</a></li>
<li role="presentation" className={ 'active' } onClick={ this.updateTabs(1) }><a>BG</a></li>
</ul>
<select name="bubgSelect" id="bu-bg-select" className="form-control">{_.map(this.props.items, (item, index) => <option key={ index }>{item}</option>)}</select>
<p className="help-block">Hold <kbd>ctrl</kbd> and click to select multiple items</p>
</div>
);
}
}
const mapStateToProps = state => ({
items: state.bubgFetching.data.rows,
});
const mapDispatchToProps = dispatch => bindActionCreators({ getParallelData }, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(BUBGContainer);
我不确定如何写一个动作来实现同样的目标。
我目前的行动是
export const getParallelData = url => (dispatch) => {
dispatch(requestGetData());
return axios.get(url)
.then((response) => {
dispatch(receiveGetData(response.data));
})
.catch((response) => {
dispatch(receiveGetError(response.data));
});
};
const requestGetData = () => ({ type: ACTION_TYPES.REQ_GET_DATA });
const receiveGetData = json => ({
type: ACTION_TYPES.RECV_GET_DATA,
data: json,
});
const receiveGetError = json => ({
type: ACTION_TYPES.RECV_GET_ERROR,
data: json,
});
我目前的减速机是
import _ from 'lodash';
import * as ACTION_TYPES from '../consts/action_types';
const initialState = {
isLoading: false,
data: [],
error: false,
};
export const isFetchingGet = (state = initialState, action) => {
const newState = _.cloneDeep(state);
switch (action.type) {
case ACTION_TYPES.RECV_GET_ERROR: {
newState.isLoading = false;
newState.data = action.data;
newState.error = true;
return newState;
}
case ACTION_TYPES.RECV_GET_DATA: {
newState.isLoading = false;
newState.data = action.data;
newState.error = false;
return newState;
}
case ACTION_TYPES.REQ_GET_DATA: {
newState.isLoading = true;
newState.error = false;
return newState;
}
default:
return state;
}
};
这个link说明了如何使用它,但不知道如何实现它。
答案 0 :(得分:2)
这是Promise.all的另一种选择,专注于您的并发请求问题。只是相关部分:
componentDidMount() {
const list = [ "bu-list, "bg-list" ];
this.props.getParallelData( list );
}
export const getParallelData = list =>
async ( dispatch ) => {
dispatch( requestGetData() );
try {
const promiseArray = list.map( el =>
axios.get( `https://localhost:3001/reports/${ el }` ) );
const response = await Promise.all( promiseArray );
return dispatch( receiveGetData( response ) );
// and map through response for data, or
// const [ buList, bgList ] = await Promise.all( promiseArray );
// return dispatch( receiveGetData( [ buList.data, bgList.data ] ) );
// or whatever form you want to pass receiveGetData
} catch ( error ) {
return dispatch( receiveGetError( error ) );
}
};
答案 1 :(得分:0)
您应该尝试使用redux-thunk或redux-saga中间件。 Thunk是更简单的选择。
https://github.com/gaearon/redux-thunk
你也可以使用async / await我发现它比promises更具可读性。
所以这是交易。您将发送函数而不是在您的动作创建者中发送对象,而redux-thunk会自动为您执行某些操作。
你会做这样的事情:
export const getParallelData = url => {
return async dispatch => {
const request = axios.get(url);
try {
if (response && response.ok) {
await dispatch({
type: ACTION_TYPES.REQ_GET_DATA,
payload: request
)}
} catch(err) {
await dispatch({
type: ACTION_TYPES.REQ_GET_DATA,
payload: err.toString()
)}
}
};
希望这有帮助!