根据文档,“没有中间件,Redux 存储只支持同步数据流”。我不明白为什么会这样。为什么容器组件不能调用异步 API,然后调用dispatch
动作?
例如,想象一个简单的 UI:一个字段和一个按钮。当用户按下按钮时,该字段将填充来自远程服务器的数据。
import * as React from 'react';
import * as Redux from 'redux';
import { Provider, connect } from 'react-redux';
const ActionTypes = {
STARTED_UPDATING: 'STARTED_UPDATING',
UPDATED: 'UPDATED'
};
class AsyncApi {
static getFieldValue() {
const promise = new Promise((resolve) => {
setTimeout(() => {
resolve(Math.floor(Math.random() * 100));
}, 1000);
});
return promise;
}
}
class App extends React.Component {
render() {
return (
<div>
<input value={this.props.field}/>
<button disabled={this.props.isWaiting} onClick={this.props.update}>Fetch</button>
{this.props.isWaiting && <div>Waiting...</div>}
</div>
);
}
}
App.propTypes = {
dispatch: React.PropTypes.func,
field: React.PropTypes.any,
isWaiting: React.PropTypes.bool
};
const reducer = (state = { field: 'No data', isWaiting: false }, action) => {
switch (action.type) {
case ActionTypes.STARTED_UPDATING:
return { ...state, isWaiting: true };
case ActionTypes.UPDATED:
return { ...state, isWaiting: false, field: action.payload };
default:
return state;
}
};
const store = Redux.createStore(reducer);
const ConnectedApp = connect(
(state) => {
return { ...state };
},
(dispatch) => {
return {
update: () => {
dispatch({
type: ActionTypes.STARTED_UPDATING
});
AsyncApi.getFieldValue()
.then(result => dispatch({
type: ActionTypes.UPDATED,
payload: result
}));
}
};
})(App);
export default class extends React.Component {
render() {
return <Provider store={store}><ConnectedApp/></Provider>;
}
}
渲染导出的组件后,我可以单击按钮并正确更新输入。
注意调用update
中的函数connect
。它调度一个告诉应用程序它正在更新的操作,然后执行一个异步调用。调用完成后,提供的值将作为另一个操作的有效负载分派。
这种方法有什么问题?正如文档所暗示的,我为什么要使用 Redux Thunk 或 Redux Promise?
编辑:我在 Redux repo 中搜索了线索,发现过去要求 Action Creator 是纯函数。例如,这里有一个用户试图为异步数据流提供更好的解释:
action creator 本身仍然是一个纯函数,但它返回的 thunk 函数不需要,它可以做我们的异步调用
动作创建者不再需要纯粹。那么,thunk/promise 中间件在过去肯定是需要的,但现在好像不再这样了?