Flag of Ukraine   We stand with the brave people of Ukraine. Stop the war. Find out how you can help.

Uppy 0.20: React, Retry & Time Travel

We are proud to present Uppy 0.20. This one focuses on React and Redux support, adding storage expirations to GoldenRetriever and upload retries. Enjoy!

Uppy React components

Uppy now ships with React components! We’ve been exploring different approaches to React components for several months, so we’re excited to finally have them in ✨ There are components for each of Uppy’s UI elements, like the Dashboard and the StatusBar.

const uppy = Uppy()
uppy.use(Tus10, { endpoint: '/upload' })

const Dashboard = require('uppy/lib/react/Dashboard')

const Uploader = () => (
    note="Hey! It's a React component!"

ReactDOM.render(<Uploader />, document.querySelector('#uploader'))

Check out the docs for more!


@richardwillars contributed a plugin that will sync Uppy’s internal state with an existing Redux store.
To use it, define a Redux action and reducer:

// The action creator receives 3 parameters:
// - The previous state
// - The new state
// - The change set
const uppyStateUpdate = (previous, next, patch) => ({

function reduce (state = {}, action) {
  if (action.type === 'UPPY_STATE_UPDATE') {
    return {
      // Merge in the changes.

Then pass your Redux store’s dispatch function and the action creator to the Redux plugin:

const ReduxStore = require('uppy/lib/Redux')

uppy.use(ReduxStore, {
  dispatch: store.dispatch,
  action: uppyStateUpdate,

See the docs

Redux DevTools

Even if you’re not using Redux in your application, there’s some Redux-related news! Uppy now has a new plugin, ReduxDevTools, which adds debug support for Redux DevTools and allows you to time travel while debugging Uppy:

To try it, add the plugin:

const ReduxDevTools = require('uppy/lib/plugins/ReduxDevTools')


And then activate the browser extension.

See #373 for details and discussion.


We’ve added a retry UI to the Dashboard. If some of your uploads fail—maybe the network is down or the endpoint is unresponsive—you’ll see this:

Uppy Dashboard retry UI with individual retry buttons and “retry all”

From here it’s easy to retry individual uploads or all at once. This feature currenty works best with Tus10 plugin, and has basic XHRUpload support, but we’ll improve on the latter in the future releases.

Re-designed Drag and Drop plugin

The old trustly DragDrop plugin has been re-designed by @arturi and @nqst:

  • Fresh simple design, arrow icon, white background;
  • New sizing options: width and height (both 100% by default to fill the entire container space);
  • A note option, like in the Dashboard, to add info about restrictions or anything else you would like your users to know.

Check it out

uppy.use(DragDrop, {
  target: 'body',
  width: '600px',
  height: '300px',
  note: 'Videos only, up to 100 MB',

The Golden Retriever cleans up after itself

We recently released the GoldenRetriever plugin, which stores selected files on the client so that it can recover them after a browser crash. Previously, these stored files would stay around forever, and clog up the user’s disk space. As of 0.20.0, files will be removed from client-side storage when they have been uploaded. Files that have had nothing happen to them for longer than 24 hours will be cleaned up automatically. This timeframe can be configured using the new expires option:

const ms = require('ms')

uppy.use(GoldenRetriever, {
  expires: ms('4 hours'),

(The ms module is great for converting text durations to milliseconds!)

This will clean up files when Uppy runs, but perhaps not every page of your app uses Uppy. If a user selected some files, but then never came back to that same page, files could still hang around for a long time. To aid this, there’s a new module that you can call to clean up Uppy’s cache without needing an Uppy instance:

const cleanup = require('uppy/lib/plugins/GoldenRetriever/cleanup')


We’ll hopefully make that require path easier to remember in the future :)

Misc good stuff

  • The GoldenRetriever now detects a serviceWorker registration automatically—it’s no longer necessary to emit an core:sw-file-ready event.
  • Request headers are now configurable in the AWS S3 plugin.
  • A new setPluginState allows plugins to set state scoped to the plugin.
  • Some unused code was removed 🎉
  • More tests were added! Thanks @gavboulton and @richardwillars 🎉
  • Documentation for the StatusBar, XHRUpload and Tus plugins.

Full Changelog

Here is the full list of changes for version 0.20.0 (and patch 0.19.1):

  • core: retry/error when upload can’t start or fails (offline, connection lost, wrong endpoint); add error in file progress state, UI, question mark button (#307 / @arturi)
  • core: support for retry in Tus plugin (#307 / @arturi)
  • core: support for retry in XHRUpload plugin (#307 / @arturi)
  • core: Add support for Redux DevTools via a plugin (#373 / @arturi)
  • core: improve and merge the React PR (#170 / @goto-bus-stop, @arturi)
  • core: improve core.log method, add timestamps (#372 / @arturi)
  • dragdrop: redesign, add note, width/height options, arrow icon (#374 / @arturi)
  • uploaders: upload resolution changes, followup to #323 (#347 / @goto-bus-stop)
  • uploaders: issue warning when no uploading plugins are used (#372 / @arturi)
  • core: fix replaceTargetContent and add tests for Plugin (#354 / @gavboulton)
  • goldenretriever: Omit completed uploads from saved file state—previously, when an upload was finished and the user refreshed the page, all the finished files would still be there because we saved the entire list of files. Changed this to only store files that are part of an in-progress upload, or that have yet to be uploaded (#358, #324 / @goto-bus-stop)
  • goldenretriever: Remove files from cache when upload finished—this uses the deleteBlobs function when core:success fires (#358, #324 / @goto-bus-stop)
  • goldenretriever: add a timestamp to cached blobs, and to delete old blobs on boot (#358, #324 / @goto-bus-stop)
  • s3: have some way to configure content-disposition for uploads, see #243 (@goto-bus-stop)
  • core: move setPluginState and add getPluginState to Plugin class (#363 / @goto-bus-stop)
  • goldenretriever: fix restorefiles with id (#351 / @arturi)
  • goldenretriever: Clean up blobs that are not related to a file in state (#349 / @goto-bus-stop)
  • core: set the newState before emiting core:state-update (#341 / @sunil-shrestha, @arturi)
  • docs: Document StatusBar plugin (#350 / @goto-bus-stop)

The Uppy Team