xplato / useUndoable

↪ React hook for undo/redo functionality (with batteries included)
MIT License
168 stars 7 forks source link

Fix recency bug in functional updaters #28

Closed KPJ-93 closed 10 months ago

KPJ-93 commented 10 months ago

In the current version, the handling of executing a functional updater results in unexpected behaviour, compared to React's own functional update handling in useState.

The situation concerns calling the setter twice before one render. According to useState, the second call should take into account the updated (but not yet rendered) value of the first update call. This is currently not the case in useUndoable, as this takes into account only the recent value latest rendered. This has to do with the functional updater being executed in the useUndoable hook, which indeed, only knows the rendered value as most recent one.

E.g. in code:


const [count, setCount] = useUndoable(0)

...
  setCount(old => old + 1); // expected: 1, actual: 1
  setCount(old => old + 1); // expected: 2, actual: 1
...

This PR fixes the issue by moving the execution of the functional updater from the hook code, to the reducer. The reducer code does take into account the value of the first update.