perf(view): reduce shell rerenders
This commit is contained in:
68
view/useAppState.test.ts
Normal file
68
view/useAppState.test.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { createInitialAppState } from "@editor/initial-state";
|
||||
import type { AppState } from "@editor/state";
|
||||
import { createAppStateSelectorSnapshot, shallowEqual } from "./useAppState";
|
||||
|
||||
describe("app state selector snapshot", () => {
|
||||
test("reuses selected snapshots when equality reports no relevant changes", () => {
|
||||
const state = createInitialAppState("Test");
|
||||
const snapshot = createAppStateSelectorSnapshot(selectShellLikeState, shallowEqual);
|
||||
const selected = snapshot.getSnapshot(state);
|
||||
const previewOnlyUpdate: AppState = {
|
||||
...state,
|
||||
editor: {
|
||||
...state.editor,
|
||||
brushStrokePreview: { layerId: "layer", assetId: "asset", source: "preview" },
|
||||
},
|
||||
};
|
||||
|
||||
expect(snapshot.updateSnapshot(previewOnlyUpdate)).toBe(false);
|
||||
expect(snapshot.getSnapshot(previewOnlyUpdate)).toBe(selected);
|
||||
});
|
||||
|
||||
test("can collapse brush preview updates to presence instead of position", () => {
|
||||
const state = createInitialAppState("Test");
|
||||
const snapshot = createAppStateSelectorSnapshot((next: AppState) => ({ hasBrushPreview: Boolean(next.editor.brushPreview) }), shallowEqual);
|
||||
const withoutPreview = snapshot.getSnapshot(state);
|
||||
const withPreview: AppState = {
|
||||
...state,
|
||||
editor: {
|
||||
...state.editor,
|
||||
brushPreview: { position: { x: 10, y: 20 } },
|
||||
},
|
||||
};
|
||||
|
||||
expect(snapshot.updateSnapshot(withPreview)).toBe(true);
|
||||
const previewPresent = snapshot.getSnapshot(withPreview);
|
||||
expect(previewPresent).not.toBe(withoutPreview);
|
||||
expect(previewPresent.hasBrushPreview).toBe(true);
|
||||
|
||||
const movedPreview: AppState = {
|
||||
...withPreview,
|
||||
editor: {
|
||||
...withPreview.editor,
|
||||
brushPreview: { position: { x: 30, y: 40 } },
|
||||
},
|
||||
};
|
||||
|
||||
expect(snapshot.updateSnapshot(movedPreview)).toBe(false);
|
||||
expect(snapshot.getSnapshot(movedPreview)).toBe(previewPresent);
|
||||
});
|
||||
|
||||
test("shallow equality uses object keys and Object.is value checks", () => {
|
||||
expect(shallowEqual({ id: "a", value: Number.NaN }, { id: "a", value: Number.NaN })).toBe(true);
|
||||
expect(shallowEqual({ id: "a", value: 0 }, { id: "a", value: -0 })).toBe(false);
|
||||
expect(shallowEqual({ id: "a" }, { id: "a", extra: true })).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
function selectShellLikeState(state: AppState) {
|
||||
return {
|
||||
document: state.document,
|
||||
selection: state.editor.selection,
|
||||
viewport: state.editor.viewport,
|
||||
tools: state.editor.tools,
|
||||
transformSession: state.editor.transformSession,
|
||||
maskEdit: state.editor.maskEdit,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user