Fix shape drag perf (#1932)

This prevents geometry from being recalculated when dragging shapes
around. It uses an equality check on the shape props to opt out of
recalculations. This still allows bounds to be calculated based on other
reactive values, so if folks really want to use x,y values or opacity or
whatever, they can call editor.getShape(id) when making their
calculation.

### Change Type

- [x] `patch` — Bug fix
- [ ] `minor` — New feature
- [ ] `major` — Breaking change
- [ ] `dependencies` — Changes to package dependencies[^1]
- [ ] `documentation` — Changes to the documentation only[^2]
- [ ] `tests` — Changes to any test code only[^2]
- [ ] `internal` — Any other changes that don't affect the published
package[^2]
- [ ] I don't know

[^1]: publishes a `patch` release, for devDependencies use `internal`
[^2]: will not publish a new version


### Release Notes

- Fixes a perf regression for dragging shapes around
pull/1927/head
David Sheldrick 2023-09-19 16:29:13 +01:00 zatwierdzone przez GitHub
rodzic db58d9c54f
commit 386a2396d1
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
3 zmienionych plików z 16 dodań i 8 usunięć

Wyświetl plik

@ -3724,9 +3724,11 @@ export class Editor extends EventEmitter<TLEventMap> {
@computed
private get _shapeGeometryCache(): ComputedCache<Geometry2d, TLShape> {
return this.store.createComputedCache('bounds', (shape) => {
return this.getShapeUtil(shape).getGeometry(shape)
})
return this.store.createComputedCache(
'bounds',
(shape) => this.getShapeUtil(shape).getGeometry(shape),
(a, b) => a.props === b.props
)
}
/**

Wyświetl plik

@ -230,7 +230,7 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
// (undocumented)
applyDiff(diff: RecordsDiff<R>, runCallbacks?: boolean): void;
clear: () => void;
createComputedCache: <T, V extends R = R>(name: string, derive: (record: V) => T | undefined) => ComputedCache<T, V>;
createComputedCache: <T, V extends R = R>(name: string, derive: (record: V) => T | undefined, isEqual?: ((a: V, b: V) => boolean) | undefined) => ComputedCache<T, V>;
createSelectedComputedCache: <T, J, V extends R = R>(name: string, selector: (record: V) => T | undefined, derive: (input: T) => J | undefined) => ComputedCache<J, V>;
// @internal (undocumented)
ensureStoreIsUsable(): void;

Wyświetl plik

@ -766,7 +766,8 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
*/
createComputedCache = <T, V extends R = R>(
name: string,
derive: (record: V) => T | undefined
derive: (record: V) => T | undefined,
isEqual?: (a: V, b: V) => boolean
): ComputedCache<T, V> => {
const cache = new Cache<Atom<any>, Computed<T | undefined>>()
return {
@ -775,9 +776,14 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
if (!atom) {
return undefined
}
return cache.get(atom, () =>
computed<T | undefined>(name + ':' + id, () => derive(atom.value as V))
).value
return cache.get(atom, () => {
const recordSignal = isEqual
? computed(atom.name + ':equals', () => atom.value, { isEqual })
: atom
return computed<T | undefined>(name + ':' + id, () => {
return derive(recordSignal.value as V)
})
}).value
},
}
}