-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: update history when a state property is set to undefined #14
Changes from 4 commits
be83807
64ff0ac
3068c23
cbccfa1
fe0d61c
1239a3d
9a8e550
e881a74
59e6c6a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -23,11 +23,14 @@ export type HistoryNode<T> = { | |||||||
updatedAt?: Date; | ||||||||
}; | ||||||||
|
||||||||
type EmptyWIP = Record<string, never>; | ||||||||
const EmptyWIP: EmptyWIP = {}; | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i still have a problem with the semantics here so how about we use a Symbol and more standard naming convention
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, I fixed the naming case and used a Symbol. |
||||||||
|
||||||||
export type History<T> = { | ||||||||
/** | ||||||||
* field for holding sandbox changes; used to avoid infinite loops | ||||||||
*/ | ||||||||
wip?: Snapshot<T>; | ||||||||
wip: Snapshot<T> | EmptyWIP; | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. given we use this once
Suggested change
|
||||||||
/** | ||||||||
* the nodes of the history for each change | ||||||||
*/ | ||||||||
|
@@ -134,7 +137,7 @@ export function proxyWithHistory<V>( | |||||||
* - history.wip: field for holding sandbox changes; used to avoid infinite loops<br> | ||||||||
*/ | ||||||||
history: ref<History<V>>({ | ||||||||
wip: undefined, // to avoid infinite loop | ||||||||
wip: EmptyWIP, // to avoid infinite loop | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also ensure the others are renamed
Suggested change
|
||||||||
nodes: [], | ||||||||
index: -1, | ||||||||
}), | ||||||||
|
@@ -230,7 +233,7 @@ export function proxyWithHistory<V>( | |||||||
if (proxyObject.canUndo()) { | ||||||||
proxyObject.history.wip = proxyObject.clone( | ||||||||
proxyObject.history.nodes[--proxyObject.history.index]?.snapshot | ||||||||
); | ||||||||
) ?? EmptyWIP | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm unsure what the expectation is. The issue says that the value is set to undefined and no history change is reflected.. but this is setting the value to an empty object when null or undefined is found. Seems like a data integrity issue. Why not just set the value externally from the lib to an empty object if that's what's required in that use case? What is the expectation here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I'm understandin correctly, the method Since by default (when empty) the history wip is Using an empty object ensures that it is equal ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still don't really get the point..if the value is undefined and you try to set it to undefined then there should be no history change.. But if it's set then that means it's not undefined. And if it sees undefined then undefined will not be equal to wip.. So what am I missing? In theory there is no benefit to changing it to an empty object. Do your test cases pass without these changes? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not the value that is The first test case fails, the second one ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks. I'll check it in detail later There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it('should update history when property is deleted', async () => {
const state = proxyWithHistory<
Partial<{ prop0: number; prop1: number; prop2: number; prop3: number }>
>({ prop0: 0, prop1: 1, prop2: 2, prop3: 3 });
await Promise.resolve();
expect(state.value.prop0).toEqual(0);
expect(state.value.prop1).toEqual(1);
expect(state.value.prop2).toEqual(2);
expect(state.value.prop3).toEqual(3);
expect(state.history.nodes.length).toEqual(1);
delete state.value.prop0;
await Promise.resolve();
expect(state.value.prop0).toEqual(undefined);
expect(state.value.prop1).toEqual(1);
expect(state.value.prop2).toEqual(2);
expect(state.value.prop3).toEqual(3);
expect(state.history.nodes.length).toEqual(2);
});
it('should update history when property is set to undefined', async () => {
const state = proxyWithHistory<
Partial<{ prop0: number; prop1: number; prop2: number; prop3: number }>
>({ prop0: 0, prop1: 1, prop2: 2, prop3: 3 });
await Promise.resolve();
expect(state.value.prop0).toEqual(0);
expect(state.value.prop1).toEqual(1);
expect(state.value.prop2).toEqual(2);
expect(state.value.prop3).toEqual(3);
expect(state.history.nodes.length).toEqual(1);
state.value.prop0 = undefined;
await Promise.resolve();
expect(state.value.prop0).toEqual(undefined);
expect(state.value.prop1).toEqual(1);
expect(state.value.prop2).toEqual(2);
expect(state.value.prop3).toEqual(3);
expect(state.history.nodes.length).toEqual(2);
}); i used these test cases without your changes to understand the issue a little better in isolation of any other property changes. first test case passes and the second one doesnt. so thanks i have a clearer understanding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice, I added your your test cases to the vanilla suite and removed mine from react suite. |
||||||||
proxyObject.value = proxyObject.history.wip as V; | ||||||||
} | ||||||||
}, | ||||||||
|
@@ -247,9 +250,10 @@ export function proxyWithHistory<V>( | |||||||
*/ | ||||||||
redo: () => { | ||||||||
if (proxyObject.canRedo()) { | ||||||||
proxyObject.history.wip = proxyObject.clone( | ||||||||
proxyObject.history.nodes[++proxyObject.history.index]?.snapshot | ||||||||
); | ||||||||
proxyObject.history.wip = | ||||||||
proxyObject.clone( | ||||||||
proxyObject.history.nodes[++proxyObject.history.index]?.snapshot | ||||||||
) ?? EmptyWIP; | ||||||||
proxyObject.value = proxyObject.history.wip as V; | ||||||||
} | ||||||||
}, | ||||||||
|
@@ -308,7 +312,9 @@ export function proxyWithHistory<V>( | |||||||
const resolvedIndex = isLastIndex ? index - 1 : index + 1; | ||||||||
const resolvedNode = proxyObject.history.nodes[resolvedIndex]; | ||||||||
|
||||||||
proxyObject.history.wip = proxyObject.clone(resolvedNode?.snapshot); | ||||||||
proxyObject.history.wip = proxyObject.clone( | ||||||||
resolvedNode?.snapshot | ||||||||
) ?? EmptyWIP; | ||||||||
proxyObject.value = proxyObject.history.wip as V; | ||||||||
|
||||||||
if (isLastIndex) proxyObject.history.index--; | ||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you dont need to adjust this.. its automated when releasing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, rolled back