feat: add memoization

This commit is contained in:
Arnošt Pleskot 2023-09-13 15:57:50 +02:00
parent dd9bde5ee7
commit b4e80b602d
No known key found for this signature in database

View file

@ -1,4 +1,5 @@
import { AppState, ScrollConstraints } from "../types";
import { isShallowEqual } from "../utils";
import { getNormalizedZoom } from "./zoom";
/**
@ -301,6 +302,15 @@ const isViewportOutsideOfConstrainedArea = (state: AppState) => {
);
};
let memoizedValues: {
previousState: Pick<
AppState,
"zoom" | "width" | "height" | "scrollConstraints"
>;
constraints: ReturnType<typeof calculateConstraints>;
constraintsWithoutOverscroll: ReturnType<typeof calculateConstraints>;
} | null = null;
/**
* Constrains the AppState scroll values within the defined scroll constraints.
*
@ -323,47 +333,75 @@ export const constrainScrollState = (
}
const { scrollX, scrollY, width, height, scrollConstraints, zoom } = state;
const constrainedValues = constrainScrollValues({
...calculateConstraints({
const canUseMemoizedValues =
memoizedValues?.previousState.scrollConstraints && // can't use memoized values if there were no scrollConstraints in memoizedValues
memoizedValues && // there are memoized values
isShallowEqual(
// current scrollConstraints are the same as in memoizedValues
state.scrollConstraints,
memoizedValues.previousState.scrollConstraints!,
) &&
isShallowEqual(
// current zoom and window dimensions are equal to those in memoizedValues
{ zoom: zoom.value, width, height },
{
zoom: memoizedValues.previousState.zoom.value,
width: memoizedValues.previousState.width,
height: memoizedValues.previousState.height,
},
);
const constraints = canUseMemoizedValues
? memoizedValues!.constraints
: calculateConstraints({
scrollConstraints,
width,
height,
zoom,
cursorButton: "down",
}),
scrollX,
scrollY,
});
const shouldAnimate = isViewportOutsideOfConstrainedArea(state);
const animateTo = shouldAnimate
? constrainScrollValues({
...calculateConstraints({
const constraintsWithoutOverscroll = canUseMemoizedValues
? memoizedValues!.constraintsWithoutOverscroll
: calculateConstraints({
scrollConstraints,
width,
height,
zoom,
cursorButton: "up",
}),
});
const constrainedValues = constrainScrollValues({
...constraints,
scrollX,
scrollY,
})
: null;
});
const animateTo = constrainScrollValues({
...constraintsWithoutOverscroll,
scrollX,
scrollY,
});
if (!canUseMemoizedValues) {
memoizedValues = {
previousState: {
zoom: state.zoom,
width: state.width,
height: state.height,
scrollConstraints: state.scrollConstraints,
},
constraints,
constraintsWithoutOverscroll,
};
}
if (
constrainedValues.scrollX !== scrollX ||
constrainedValues.scrollY !== scrollY
) {
return {
state: {
...state,
...constrainedValues,
},
shouldAnimate,
shouldAnimate: isViewportOutsideOfConstrainedArea(state),
animateTo,
};
}
return { state, shouldAnimate, animateTo };
};