Avoid excessive re-render when setting same reference/value in snapshot (#32918)

* perf: avoid excessive re-render when setting same value in snapshot

* test: update tests
This commit is contained in:
Florian Duros
2026-03-25 15:23:11 +00:00
committed by GitHub
parent d0a564d578
commit 1025d60001
5 changed files with 25 additions and 5 deletions
@@ -27,9 +27,13 @@ export class Snapshot<T> {
/**
* Update a part of the current snapshot by merging into the existing snapshot.
* Only emits if at least one of the merged fields has a different reference than the current value.
* @param snapshot A subset of the snapshot to merge into the current snapshot.
*/
public merge(snapshot: Partial<T>): void {
const keys = Object.keys(snapshot) as Array<keyof T>;
const hasChanged = keys.some((key) => !Object.is(snapshot[key], this.snapshot[key]));
if (!hasChanged) return;
this.snapshot = { ...this.snapshot, ...snapshot };
this.emit();
}
@@ -40,4 +40,20 @@ describe("Snapshot", () => {
snapshot.merge({ key2: 10 });
expect(snapshot.current).toStrictEqual({ key1: "foo", key2: 10, key3: false });
});
it("should not emit when merged values are unchanged", () => {
const emit = vi.fn();
const snapshot = new Snapshot<TestSnapshot>({ key1: "foo", key2: 5, key3: false }, emit);
snapshot.merge({ key1: "foo", key2: 5 });
expect(emit).not.toHaveBeenCalled();
expect(snapshot.current).toStrictEqual({ key1: "foo", key2: 5, key3: false });
});
it("should emit when at least one merged value differs", () => {
const emit = vi.fn();
const snapshot = new Snapshot<TestSnapshot>({ key1: "foo", key2: 5, key3: false }, emit);
snapshot.merge({ key1: "foo", key2: 10 });
expect(emit).toHaveBeenCalledTimes(1);
expect(snapshot.current).toStrictEqual({ key1: "foo", key2: 10, key3: false });
});
});