project-minimek icon indicating copy to clipboard operation
project-minimek copied to clipboard

Debouncing inputs means that there's a time period where the Redux state is incorrect

Open shepmaster opened this issue 6 years ago • 0 comments

To reproduce:

  1. Increase the default debounce time:

    diff --git a/src/common/components/FormEditWrapper.jsx b/src/common/components/FormEditWrapper.jsx
    index 2276e58..800c4a0 100644
    --- a/src/common/components/FormEditWrapper.jsx
    +++ b/src/common/components/FormEditWrapper.jsx
    @@ -24,7 +24,7 @@ class FormEditWrapper extends Component {
             onChangePropName : "onChange",
             singleValue : false,
             passIsEditing : true,
    -        dispatchDelay : 250,
    +        dispatchDelay : 2500,
         }
    
         constructor(props) {
    

    This isn't required, but it makes it much easier to demonstrate.

  2. Create a new pilot, set the name, and save the changes:

    debounce

    (please ignore the failure at the end, it seems to be an unrelated issue)

  3. Note that the state saved to the store does not have the entered pilot name:

    Pilot: {
      items: [
        'cjrb9jhul00003f5viun8eqwk'
      ],
      itemsById: {
        cjrb9jhul00003f5viun8eqwk: {
          name: 'New Pilot',  // <------- HERE
          rank: 'Private',
          gunnery: 4,
          piloting: 5,
          age: 25,
          id: 'cjrb9jhul00003f5viun8eqwk'
        }
      },
      meta: {
        maxId: null
      }
    }
    
    Relevant Actions
    {
      type: 'PILOT_EDIT_START'
    }
    
    {
      type: 'PILOT_EDIT_STOP'
    }
    
    {
      type: 'EDIT_ITEM_APPLY',
      payload: {
        itemType: 'Pilot',
        itemID: 'cjrb9jhul00003f5viun8eqwk'
      }
    }
    
    {
      type: 'EDIT_ITEM_STOP',
      payload: {
        itemType: 'Pilot',
        itemID: 'cjrb9jhul00003f5viun8eqwk'
      }
    }
    
    {
      type: 'PILOT_SELECT',
      payload: {
        currentPilot: null
      }
    }
    

If you wait for the debounce timeout length after editing, then you will get an additional action and the application works:

{
  type: 'EDIT_ITEM_UPDATE',
  payload: {
    itemType: 'Pilot',
    itemID: 'cjrb9rai700003f5vqeja41be',
    newItemAttributes: {
      name: 'hello'
    }
  }
}

Relatedly, it's my understanding that in general you should make use of the debounced function's .clear() or .flush() methods when the component is unmounted, otherwise you might call the function after the component is gone. This isn't a problem with this example, but in a larger one that makes use of this it could be and React will warn about it.

If you do use flush(), you might get a state update "too late", which can cause strange issues. In our case, the UI was updated and thus it "looked right", but the data was never sent to the backend.


In our case, we triggered this type of behavior by using automated tests. These tend to be much faster at entering data and submitting forms.

shepmaster avatar Jan 24 '19 23:01 shepmaster