Why do we need middleware for async flow in Redux?
<p>According to the docs, <a href="http://redux.js.org/docs/advanced/AsyncFlow.html" rel="noreferrer">"Without middleware, Redux store only supports synchronous data flow"</a>. I don't understand why this is the case. Why can't the container component call the async API, and then <code>dispatch</code> the actions? </p>

<p>For example, imagine a simple UI: a field and a button. When user pushes the button, the field gets populated with data from a remote server.</p>

<p><a href="https://i.stack.imgur.com/GBI59.png" rel="noreferrer"><img src="https://i.stack.imgur.com/GBI59.png" alt="A field and a button"></a></p>

<pre><code>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) =&gt; {
            setTimeout(() =&gt; {
                resolve(Math.floor(Math.random() * 100));
            }, 1000);
        });
        return promise;
    }
}

class App extends React.Component {
    render() {
        return (
            &lt;div&gt;
                &lt;input value={this.props.field}/&gt;
                &lt;button disabled={this.props.isWaiting} onClick={this.props.update}&gt;Fetch&lt;/button&gt;
                {this.props.isWaiting &amp;&amp; &lt;div&gt;Waiting...&lt;/div&gt;}
            &lt;/div&gt;
        );
    }
}
App.propTypes = {
    dispatch: React.PropTypes.func,
    field: React.PropTypes.any,
    isWaiting: React.PropTypes.bool
};

const reducer = (state = { field: 'No data', isWaiting: false }, action) =&gt; {
    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) =&gt; {
        return { ...state };
    },
    (dispatch) =&gt; {
        return {
            update: () =&gt; {
                dispatch({
                    type: ActionTypes.STARTED_UPDATING
                });
                AsyncApi.getFieldValue()
                    .then(result =&gt; dispatch({
                        type: ActionTypes.UPDATED,
                        payload: result
                    }));
            }
        };
    })(App);
export default class extends React.Component {
    render() {
        return &lt;Provider store={store}&gt;&lt;ConnectedApp/&gt;&lt;/Provider&gt;;
    }
}
</code></pre>

<p>When the exported component is rendered, I can click the button and the input is updated correctly. </p>

<p>Note the <code>update</code> function in the <code>connect</code> call. It dispatches an action that tells the App that it is updating, and then performs an async call. After the call finishes, the provided value is dispatched as a payload of another action.</p>

<p>What is wrong with this approach? Why would I want to use Redux Thunk or Redux Promise, as the documentation suggests?</p>

<p><strong>EDIT:</strong> I searched the Redux repo for clues, and found that Action Creators were required to be pure functions in the past. For example, <a href="https://github.com/reactjs/redux/issues/533" rel="noreferrer">here's a user trying to provide a better explanation for async data flow:</a></p>

<blockquote>
  <p>The action creator itself is still a pure function, but the thunk function it returns doesn't need to be, and it can do our async calls</p>
</blockquote>

<p><a href="https://github.com/reactjs/redux/issues/1088" rel="noreferrer">Action creators are no longer required to be pure.</a> So, thunk/promise middleware was definitely required in the past, but it seems that this is no longer the case?</p>