title: Queuing Actions in Redux
body: <p>I've currently got a situation whereby I need Redux Actions to be run consecutively. I've taken a look at various middlewares, such a redux-promise, which seem to be fine <em>if you know what the successive actions are at the point of the root (for lack of a better term) action being triggered</em>.</p>
  
  <p>Essentially, I'd like to maintain a queue of actions that can be added to at any point. Each object has an instance of this queue in its state and dependent actions can be enqueued, processed and dequeued accordingly. I have an implementation, but in doing so I'm accessing state in my action creators, which feels like an anti-pattern.</p>
  
  <p>I'll try and give some context on use case and implementation.</p>
  
  <h2>Use Case</h2>
  
  <p>Suppose you want to create some lists and persist them on a server. On list creation, the server responds with an id for that list, which is used in subsequent API end points pertaining to the list:</p>
  
  <pre><code>http://my.api.com/v1.0/lists/           // POST returns some id
  http://my.api.com/v1.0/lists/&lt;id&gt;/items // API end points include id
  </code></pre>
  
  <p>Imagine that the client wants to perform optimistic updates on these API points, to enhance UX - nobody likes looking at spinners. So when you create a list, your new list instantly appears, with an option at add items:</p>
  
  <pre><code>+-------------+----------+
  |  List Name  | Actions  |
  +-------------+----------+
  | My New List | Add Item |
  +-------------+----------+
  </code></pre>
  
  <p>Suppose that someone attempts to add an item before the response from the initial create call has made it back. The items API is dependent on the id, so we know we can't call it until we have that data. However, we might want to optimistically show the new item and enqueue a call to the items API so that it triggers once the create call is done.</p>
  
  <h2>A Potential Solution</h2>
  
  <p>The method I'm using to get around this currently is by giving each list an action queue - that is, a list of Redux actions that will be triggered in succession.</p>
  
  <p>The reducer functionality for a list creation might look something like this:</p>
  
  <pre><code>case ADD_LIST:
    return {
      id: undefined, // To be filled on server response
      name: action.payload.name,
      actionQueue: []
    }
  </code></pre>
  
  <p>Then, in an action creator, we'd enqueue an action instead of directly triggering it:</p>
  
  <pre><code>export const createListItem = (name) =&gt; {
      return (dispatch) =&gt; {
          dispatch(addList(name));  // Optimistic action
          dispatch(enqueueListAction(name, backendCreateListAction(name));
      }
  }
  </code></pre>
  
  <p>For brevity, assume the backendCreateListAction function calls a fetch API, which dispatches messages to dequeue from the list on success/failure.</p>
  
  <h2>The Problem</h2>
  
  <p>What worries me here is the implementation of the enqueueListAction method. This is where I'm accessing state to govern the advancement of the queue. It looks something like this (ignore this matching on name - this actually uses a clientId in reality, but I'm trying to keep the example simple):</p>
  
  <pre><code>const enqueueListAction = (name, asyncAction) =&gt; {
      return (dispatch, getState) =&gt; {
          const state = getState();
  
          dispatch(enqueue(name, asyncAction));{
  
          const thisList = state.lists.find((l) =&gt; {
              return l.name == name;
          });
  
          // If there's nothing in the queue then process immediately
          if (thisList.actionQueue.length === 0) {
              asyncAction(dispatch);
          } 
      }
  }
  </code></pre>
  
  <p>Here, assume that the enqueue method returns a plain action that inserts an async action into the lists actionQueue. </p>
  
  <p>The whole thing feels a bit against the grain, but I'm not sure if there's another way to go with it. Additionally, since I need to dispatch in my asyncActions, I need to pass the dispatch method down to them.</p>
  
  <p>There is similar code in the method to dequeue from the list, which triggers the next action should one exist:</p>
  
  <pre><code>const dequeueListAction = (name) =&gt; {
      return (dispatch, getState) =&gt; {
          dispatch(dequeue(name));
  
          const state = getState();
          const thisList = state.lists.find((l) =&gt; {
              return l.name === name;
          });
  
          // Process next action if exists.
          if (thisList.actionQueue.length &gt; 0) {
              thisList.actionQueue[0].asyncAction(dispatch);
      }
  }
  </code></pre>
  
  <p>Generally speaking, I can live with this, but I'm concerned that it's an anti-pattern and there might be a more concise, idiomatic way of doing this in Redux.</p>
  
  <p>Any help is appreciated.</p>