10 Tips for Better Redux Architecture
Eric Elliott

Great advice, especially for testing strategy. I have one question.

How would you debounce changes in a typical <input> element? I have a React component that wraps a text input and takes an onChange property, which is a pretty common use case. I’d like the component to only call its onChange listener with the new text after there haven’t been any changes after a short delay.

I see three options:

  1. Debounce in the component. The component could have its own method onChange, which calls clearTimeout(this.timeoutId) and then this.timeoutId = setTimeout(this.notifyListener, DELAY).
  2. Use redux-thunk or similar and debounce in the action creator. The action creator could have a timeoutID in scope which it uses to schedule and cancel dispatching the action.
  3. Debounce in react-redux’s connect. The mapDispatchToProps function would wrap the action creator with a function to debounce actual calls to dispatch(), and pass that to the component’s onChange.

My preference is #1. It’s harder to test the component, but not that much harder thanks to great React tooling (I’m using Enzyme) and especially timer mocks from Jest or Sinon.

Option #2 seems to be the most “flux” way of doing it, but I’d rather avoid it if this the only thing that would use redux-thunk.

Option #3 doesn’t require additional libraries, but at the cost of hiding this state in a selector, of all places.

Do you have a preference for how to handle these barely-stateful interactions?