在非常基础的层面上,您需要将异步操作从减速器中移出。相反,您应该fetch()
在您的动作创建者中触发 并在fetch()
完成并解析您的 JSON 响应后分派一个动作。它看起来像下面这样。这个例子使用redux-thunk作为异步中间件。添加了一个额外的动作来表示何时fetch()
开始调用以及何时接收和解析数据。这可用于显示加载消息或可能禁用和/或有条件地呈现特定内容。
我创建了一个工作示例。
店铺:
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
到内部动作之类的动作是如何起作用的。这用于将动作/有效负载分派给减速器。reducer 应该只需要准备好使用的数据来更新状态。
希望这有帮助!