Re-rendering a draft when draft is modified
🙋♂ Question
Similar to #869. Is it possible to add a callback or handler or mutated object when a draft is modified? The use-case is re-rendering a draft when it has been modified.
Currently I'm trying to use valtio (which itself uses useSyncExternalStore) to re-render a draft state on mutation. However, due to the copy-on-write mechanism, immer does not directly mutate the base object and instead modifies state.copy_ .
As a result, useSyncExternalStore is unable to subscribe and or detect a difference in the base object and re-render.
A workaround that I'm considering is
state.draft = createDraft(...);
state.draft.mutate();
// valtio wraps state in a proxy and catches the set on state, and does deep object comparison to re-render
// it cannot catch changes to state.draft however since draft mutations do not propagate changes to base object
state.currentState = current(state.draft);
// in a component
const {currentState} = useSnapshot(state)
Ideally, this could maybe be
state.draft = createDraft(...);
state.draft.mutate();
// in a component
const {draft: currentState} = useSnapshot(state)
The problem in general I'm trying to solve with this approach has an easy analogy in git
- I have a working branch (
original(draft)) with some changes uncommitted (current(draft)) - I want the uncommitted changes to re-render but not change
original(draft) - I need to be able to create off-screen changes starting from
original(draft), to which my uncommitted changes could rebase to later on
Link to repro
https://codesandbox.io/s/hidden-tree-s4uo6k?file=/src/App.js