title: Redux thunk design for file upload, including cancel and progress
body: <p>Wanting to upload some files in react-redux, I got the following idea :</p>
  
  <ul>
  <li>Set a redux-thunk <code>uploadFile</code> action, which initiate the upload, taking a <code>File</code> descriptor as parameter</li>
  <li>Define my own "file descriptor" serializable in the store (with a <code>uuid</code>, a <code>pending</code>, a <code>sent</code>, a <code>errored</code> and a <code>pending</code> properties</li>
  <li>Set some other FSA like <code>addFile</code>, <code>removeFile</code>, <code>setFileErrored</code>, <code>setFileSent</code>, <code>setFileSent</code></li>
  </ul>
  
  <p>like so</p>
  
  <p><em>reducer</em></p>
  
  <pre><code>  switch (action.type) {
      case FILES__ADD_FILE:
        return {
          ...state,
          files: [
            ...state.files,
            action.payload
          ]
        }
      case FILES__REMOVE_FILE:
        return {
          ...state,
          files: state.files.filter(
            file =&gt; file.id !== action.payload
          )
        }
      case FILES__SET_FILE_ERRORED:
        return {
          ...state,
          files: state.files.map(file =&gt; {
            if(file.id !== action.payload.fileId) {
              return file
            }
  
            return {
              ...file,
              sending: false,
              errored: true,
              sent: false
            }
          })
        }
      case FILES__SET_FILE_SENDING:
        return {
          ...state,
          files: state.files.map(file =&gt; {
            if(file.id !== action.payload) {
              return file
            }
  
            return {
              ...file,
              sending: true,
              errored: false,
              sent: false
            }
          })
        }
      case FILES__SET_FILE_SENT:
        return {
          ...state,
          files: state.files.map(file =&gt; {
            if(file.id !== action.payload) {
              return file
            }
  
            return {
              ...file,
              sending: false,
              errored: false,
              sent: true
            }
          })
        }
      case FILES__SET_FILE_PROGRESS:
        return {
          ...state,
          files: state.files.map(file =&gt; {
            if(file.id !== action.payload.fileId) {
              return file
            }
  
            return {
              ...file,
              progress: action.payload.progress
            }
          })
        }
      default:
        return state
    }
  </code></pre>
  
  <p><em>actions</em></p>
  
  <pre><code>// skipping static actions
  
  export const uploadFile = (actualFile) =&gt; {
    const file = {
      id: uuidv4(),
      sending: false,
      sent: false,
      errored: false
    }
  
    return (dispatch) =&gt; {
      dispatch(addFile({
        ...file,
        sending: true
      }))
  
      return uploadFile(actualFile, {
        onUploadProgress: (evt) =&gt; {
          if(evt.loaded &amp;&amp; evt.total) {
            const progress = (evt.loaded / evt.total) * 100
  
            dispatch(setFileProgress(file.id, progress))
          }
        }
      })
      .then((fileUrl) =&gt; {
        dispatch(setFileSent(file.id))
        dispatch(setFileUrl(file.id, url))
      })
      .catch((err) =&gt; {
        console.log(err)
        dispatch(setFileErrored(file.id))
      })
    }
  }
  </code></pre>
  
  <p><strong>note</strong> : <code>uploadFile</code> is a helper of mine, wrapping an axios promise.
  The first parameter is a <code>File</code> descriptor, the second one is an axios options object.</p>
  
  <p>Which I believe should work..</p>
  
  <p>But now I'm struggling with some design questions :</p>
  
  <ul>
  <li>Is that the correct way to do it ? I mean:
  
  <ul>
  <li>this is full of impurities, but ajax queries by nature are Impure..</li>
  <li>I'm completely loosing the <code>File</code> descriptor reference, thus disallowing any chance to access it later (eg. for <code>preview</code>). Where would I store it ? I find this so bad to store it in the store, mainly because we can't purely update a <code>File</code> descriptor with ES6 stuff, and thus we need to mutate it</li>
  </ul></li>
  <li>Axios provide a neat <code>CancelToken</code> stuff, which I can pass to my options. I've been using it before in React, but switching to redux, the same question come to me : if I define a <code>cancelToken</code> in <code>uploadFile()</code>, where do I store it, so I can access it inside a further, say, <code>cancelFileUpload(fileId)</code> thunk action ?</li>
  </ul>