В соответствии с документами "Без промежуточного программного обеспечения, хранилище Redux поддерживает только синхронный поток данных" . Я не понимаю, почему это так. Почему компонент контейнера не может вызвать асинхронный API, а затем dispatch
действия?
Например, представьте простой пользовательский интерфейс: поле и кнопку. Когда пользователь нажимает кнопку, поле заполняется данными с удаленного сервера.
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
. Он отправляет действие, которое сообщает App, что оно обновляется, а затем выполняет асинхронный вызов. После завершения вызова предоставленное значение отправляется как полезная нагрузка другого действия.
Что не так с этим подходом? Почему я хочу использовать Redux Thunk или Redux Promise, как предполагает документация?
EDIT: Я искал репозиторий Redux для подсказок и обнаружил, что Action Creators должны были быть чистыми функциями в прошлом. Например, здесь пользователь пытается лучше объяснить поток асинхронных данных:
Сам создатель действия по-прежнему является чистой функцией, но функция thunk, которую она возвращает, не требуется, и она может выполнять наши асинхронные вызовы
Создателям действий больше не требуется быть чистыми. Таким образом, в прошлом было обязательно требовалось промежуточное ПО, которое, вероятно, требовалось, но кажется, что это это уже не так?