BowlingX/ra-postgraphile

Feature request: Update only changed fields

zenflow opened this issue · 2 comments

In UPDATE requests, we should ideally not include fields that are unchanged. Besides being unnecessary, it can cause issues:

  1. Conflicts can happen when different users edit different fields of same record at same time. In this scenario, one user's changes will get undone. Similarly, if an automatic process (e.g. e-commerce checkout) updates a field (e.g. inventoryCount) while a user is editing another field of the same record, then when the user clicks Save, the update from the automatic process will be undone.
  2. A user may not have permission to update every field. In this scenario they will get permissions errors when they try to edit the fields they do have permission to edit.

react-admin's UpdateParams objects have a previousData property that you can compare with data to see which fields have been changed:
https://github.com/marmelab/react-admin/blob/0796893e4989716cb6e11a5cfef767a2ed4c263e/packages/ra-core/src/types.ts#L171-L176

@BowlingX Are you open to a PR to implement this feature request?

I think this could be done by

  1. Implement getChangedData(updateParams: UpdateParams)
  2. Change this line:
    updateParams.data,

    to getChangedData(updateParams)

getChangedData() would look something like this:

function getChangedData(updateParams: UpdateParams) {
  const { data, previousData } = updateParams
  const result = {}
  for (const key of Object.keys(data) {
    if (!isDeepEqual(data[key], previousData[key)) {
      result[key] = data[key]
    }
  }
  return result
}

where isDeepEqual is fast-deep-equal which is tiny: https://bundlephobia.com/package/fast-deep-equal@2.0.1

Of course, the alternative to pulling in this new dependency would be JSON.stringify(a) === JSON.stringify(b) but that can give false negatives if order of properties don't match (not really sure if that would be a concern in this case).

Hey :) thank you for the suggestion. I think that makes sense. Feel free to create a PR :).

There might be some edge cases though (like what todo when all fields are equal and we do not have any changeset).