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 { AppState, ScrollConstraints } from "../types";
import { isShallowEqual } from "../utils";
import { getNormalizedZoom } from "./zoom"; 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. * 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 { scrollX, scrollY, width, height, scrollConstraints, zoom } = state;
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",
});
const constraintsWithoutOverscroll = canUseMemoizedValues
? memoizedValues!.constraintsWithoutOverscroll
: calculateConstraints({
scrollConstraints,
width,
height,
zoom,
cursorButton: "up",
});
const constrainedValues = constrainScrollValues({ const constrainedValues = constrainScrollValues({
...calculateConstraints({ ...constraints,
scrollConstraints,
width,
height,
zoom,
cursorButton: "down",
}),
scrollX, scrollX,
scrollY, scrollY,
}); });
const shouldAnimate = isViewportOutsideOfConstrainedArea(state); const animateTo = constrainScrollValues({
...constraintsWithoutOverscroll,
scrollX,
scrollY,
});
const animateTo = shouldAnimate if (!canUseMemoizedValues) {
? constrainScrollValues({ memoizedValues = {
...calculateConstraints({ previousState: {
scrollConstraints, zoom: state.zoom,
width, width: state.width,
height, height: state.height,
zoom, scrollConstraints: state.scrollConstraints,
cursorButton: "up",
}),
scrollX,
scrollY,
})
: null;
if (
constrainedValues.scrollX !== scrollX ||
constrainedValues.scrollY !== scrollY
) {
return {
state: {
...state,
...constrainedValues,
}, },
shouldAnimate, constraints,
animateTo, constraintsWithoutOverscroll,
}; };
} }
return { state, shouldAnimate, animateTo }; return {
state: {
...state,
...constrainedValues,
},
shouldAnimate: isViewportOutsideOfConstrainedArea(state),
animateTo,
};
}; };