Skip to content

Commit

Permalink
Masonry: Update container measurement logic for V2 (#3876)
Browse files Browse the repository at this point in the history
  • Loading branch information
liuyenwei authored Nov 15, 2024
1 parent ad4f5df commit 2d61f20
Showing 1 changed file with 17 additions and 12 deletions.
29 changes: 17 additions & 12 deletions packages/gestalt/src/MasonryV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ function useScrollContainer({
const containerOffset = useRef(0);
const scrollPos = useRef(0);

useEffect(() => {
// reset scroll position whenever the scrollContainer changes
scrollPos.current = scrollContainer ? getScrollPos(scrollContainer) : 0;
}, [scrollContainer]);

const measureContainer = useCallback(() => {
if (scrollContainer) {
containerHeight.current = getElementHeight(scrollContainer);
Expand All @@ -259,16 +264,20 @@ function useScrollContainer({
}
}, [gridWrapper, scrollContainer]);

useEffect(() => {
// measure the container whenever the gridWrapper or scrollContainer changes (we use the identity of the measureContainer function here as an indication of that)
measureContainer();
}, [measureContainer]);

// created a debounced version of measureContainer to avoid measuring the container on every render
// this is mostly because the calls to getBoundingClientRect are expensive and result in forced reflows
const measureContainerAsync = useMemo(() => debounce(measureContainer, 100), [measureContainer]);

if (containerHeight.current === 0 && containerOffset.current === 0) {
// initialize value on first render
// doing this here vs in the `useRef` to avoid measureContainer always being called
// https://18.react.dev/reference/react/useRef#avoiding-recreating-the-ref-contents
measureContainer();
}
useEffect(() => {
// trigger an async measurement whenever an update occurs
// todo - followup on this and figure out a more ideal way to handle this.
measureContainerAsync();
});

const subscribeToScrollEvent = useCallback(
(callback: () => void) => {
Expand All @@ -291,12 +300,6 @@ function useScrollContainer({
() => 0,
);

useEffect(() => {
// trigger an async measurement whenever an update occurs
// todo - followup on this and figure out a more ideal way to handle this.
measureContainerAsync();
});

return {
containerHeight: containerHeight.current,
containerOffset: containerOffset.current,
Expand Down Expand Up @@ -476,6 +479,7 @@ function useLayout<T>({
// - itemMeasurementsCount: if we have a change in the number of items we've measured, we should always recalculage
// - canPerformLayout: if we don't have a width, we can't calculate positions yet. so recalculate once we're able to

// eslint-disable-next-line react-compiler/react-compiler
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [itemMeasurementsCount, items, canPerformLayout, heightUpdateTrigger]);

Expand Down Expand Up @@ -773,6 +777,7 @@ function Masonry<T>(
hasSetInitialWidth.current = true;
}

// eslint-disable-next-line react-compiler/react-compiler
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [width]);

Expand Down

0 comments on commit 2d61f20

Please sign in to comment.