-
Notifications
You must be signed in to change notification settings - Fork 242
Description
export class UndoRedoState {
constructor(val) {
this.history = #[];
this.currentIdx = track(-1);
this.currentState = track(() => this.history[this.@currentIdx]);
this.canUndo = track(() => this.@currentIdx > 0);
this.canRedo = track(() => this.@currentIdx < this.history.length - 1);
this.canReset = track(() => this.@canUndo || this.@canRedo);
this.length = track(() => this.history.length);
this.isAtLatestState = track(() => this.@currentIdx === this.history.length - 1);
this.state = val
}
get state() {
return this.@currentState;
}
set state(val) {
if (!this.@isAtLatestState) this.history.splice(this.@currentIdx + 1);
this.history[++this.@currentIdx] = val;
}
....
}
export default component Test() {
let count = track(0, (current) => current, (next, prev) => {
undoRedoState.state = next
return next
});
let undoRedoState = new UndoRedoState(@count)
<button onclick={() => @count++}>{"Increment"}</button>
<p>{"Count: " + undoRedoState.state}</p>
<button onclick={() => undoRedoState.undo()}>{"Undo"}</button>
<button onclick={() => undoRedoState.redo()}>{"Redo"}</button>
<button onclick={() => undoRedoState.reset()}>{"Reset"}</button>
<pre>{undoRedoState.toString()}</pre>
}
In this example, Im using the set function of count to track its updates to perform undoRedoState.state = next.
This is a bit awkward, so instead, I want to perform undoRedoState.state = next inside the UndoRedoState class itself. For that I need a callback that triggers whenever count is set.
Instead of let undoRedoState = new UndoRedoState(@count) I want to pass the unwrapped count, let undoRedoState = new UndoRedoState(count) and inside the constructor of UndoRedoState I would want a callback to be triggered whenever count is set, just like what the set function does.
I know there is effect, but the trouble is I would have to use untrack inside it because I want to update some state of UndoRedoState (see set state(val) method) inside the effect whenever the count is set.
I think just like set allows for intercepting updates, a similar API could be provided to track updates in a foreign scope when the tracked value is transported from its declared scope.
Something like on(count, 'set' | 'get', () => {}) or count.onSet = callback or something else.