我正在使用react redux,并尝试调用rest-api,并返回数据。 提取是异步的,仅在提取完成后才需要返回值。
我尝试了以下操作,但这种方法无法正常运行(在带有星号的行上没有“等待”)-我该怎么办?
代码:
-----
var _getData = function()
{
return new Promise((resolve, reject) => {
let options = {
method: 'GET',
}
let _url = "my web return json";
fetch(_url, options)
.then(response =>
response.json().
then(data => resolve({
data: data,
status: response.status
}))
.catch(err => reject(
{error_data: err}
)
)
)
.catch(
err =>
{
console.log(err);
reject(err);
}
)
})
}
// ...
const reducer = (state = initialState, action) => {
if (action.type === 'GET_DATA_FIRST') {
let x = {}
setTimeout(function () {
_getData().then(
(res) =>
{
x = res;
}
) }, 0)
// ******** NEED TO WAIT UTIL _getData ends and return a value *****
return {
...state,
myData: x
}
}
return state;
};
谢谢。
答案 0 :(得分:2)
在非常基本的级别上,您需要将异步操作从减速器中移出。相反,您应该在动作创建者中触发fetch()
,并在fetch()
完成并解决JSON响应后调度动作。它看起来像以下内容。本示例将redux- thunk用于异步中间件。添加了一个附加操作,以表示fetch()
调用何时开始以及何时接收和解析数据。这可以用于显示加载消息,或者可以禁用和/或有条件地渲染特定内容。
我已经创建了一个有效的example。
商店:
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
const middleware = [ thunk ];
const store = createStore(
rootReducer,
applyMiddleware(...middleware)
);
export default store;
减速器:
import { combineReducers } from 'redux';
import { GET_DATA_FIRST, REQUEST_DATA } from '../actions';
const initialState = {
isFetching: false,
myData: []
};
const things = (state = initialState, action) => {
switch (action.type) {
case REQUEST_DATA:
return {
...state,
isFetching: true
};
case GET_DATA_FIRST:
return {
...state,
isFetching: false,
myData: action.myData
};
default:
return state;
}
};
const rootReducer = combineReducers({
things // this key can be called anything, 'things' is just an example
});
export default rootReducer;
操作:
export const REQUEST_DATA = 'REQUEST_DATA'; // action to represent waiting for response
export const GET_DATA_FIRST = 'GET_DATA_FIRST'; // action to represent receiving of data
export const requestData = () => ({ type: REQUEST_DATA });
export const getDataFirst = myData => ({ type: GET_DATA_FIRST, myData });
export const fetchData = () => dispatch => {
dispatch(requestData());
return getData().then(things => {
// simulated delay
setTimeout(() => {
return dispatch(getDataFirst(things))
}, 1000);
});
};
const getData = () => {
return fetch('https://jsonplaceholder.typicode.com/todos').then(res => res.json());
}
组件:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchData } from './actions';
class ThingsList extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.props.dispatch(fetchData());
}
render() {
return (
<div>
<button type="button" onClick={this.handleClick}>GET DATA</button>
{this.props.isFetching && <div>Loading...</div>}
<ul>
{this.props.myData.map(d => <li key={d.id}>{d.title}</li>)}
</ul>
</div>
);
}
}
const mapStateToProps = ({ things: { myData, isFetching } }) => ({
myData,
isFetching
});
export default connect(mapStateToProps)(ThingsList);
注意诸如fetchData()
之类的动作如何将dispatch
传递给内部动作函数。这用于将操作/有效负载分配给减速器。减速器应该只获取准备使用的数据来更新状态。
希望有帮助!