Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 65 additions & 1 deletion src/__tests__/RecyclerView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "@quilted/react-testing/matchers";
import { render } from "@quilted/react-testing";

import { FlashListRef } from "../FlashListRef";
import { FlashList } from "..";
import { FlashList, FlashListProps } from "..";

// Mock measureLayout to return fixed dimensions
jest.mock("../recyclerview/utils/measureLayout", () => {
Expand Down Expand Up @@ -398,6 +398,70 @@ describe("RecyclerView", () => {
});
});

describe("onChangeStickyIndex previous index", () => {
const scrollTo = (root: ReturnType<typeof render>, y: number) => {
const scrollable = root.findWhere((node: any) => node.props.onScroll);
if (!scrollable) throw new Error("Could not find scrollable component");

const onScroll: any = scrollable.prop("onScroll" as never);
root.act(() => {
onScroll({
nativeEvent: {
contentOffset: { x: 0, y },
contentSize: { width: 399, height: 2000 },
layoutMeasurement: { width: 399, height: 899 },
},
});
});
};

// Each item is 100px tall, so with stickyHeaderIndices=[0, 5, 10, 15]
// header 5 sits at y=500 and header 10 at y=1000.
const renderWithStickyHeaders = (
stickyHeaderConfig?: FlashListProps<number>["stickyHeaderConfig"]
) => {
const onChangeStickyIndex = jest.fn();
const result = render(
<FlashList
data={[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19,
]}
renderItem={({ item }) => <Text>{item}</Text>}
stickyHeaderIndices={[0, 5, 10, 15]}
stickyHeaderConfig={stickyHeaderConfig}
onChangeStickyIndex={onChangeStickyIndex}
overrideProps={{ initialDrawBatchSize: 1 }}
drawDistance={0}
/>
);

return { result, onChangeStickyIndex };
};

it("reports the previously stuck index with the default config", () => {
const { result, onChangeStickyIndex } = renderWithStickyHeaders();

scrollTo(result, 550);
expect(onChangeStickyIndex).toHaveBeenLastCalledWith(5, 0);

scrollTo(result, 1050);
expect(onChangeStickyIndex).toHaveBeenLastCalledWith(10, 5);
});

it("reports the previously stuck index when hideRelatedCell is enabled", () => {
const { result, onChangeStickyIndex } = renderWithStickyHeaders({
hideRelatedCell: true,
});

scrollTo(result, 550);
expect(onChangeStickyIndex).toHaveBeenLastCalledWith(5, 0);

scrollTo(result, 1050);
expect(onChangeStickyIndex).toHaveBeenLastCalledWith(10, 5);
});
});

describe("autoscrolling to bottom is suppressed while offset projection is disabled", () => {
const scrollTo = (root: ReturnType<typeof render>, y: number) => {
const scrollable = root.findWhere((node: any) => node.props.onScroll);
Expand Down
11 changes: 9 additions & 2 deletions src/recyclerview/RecyclerView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ const RecyclerViewComponent = <T,>(
// Refs for sticky headers and scroll anchoring
const stickyHeaderRef = useRef<StickyHeaderRef>(null);
const scrollAnchorRef = useRef<ScrollAnchorRef>(null);
// Last sticky index reported to `onChangeStickyIndex`. Tracked separately
// from `currentStickyIndex` because that state is only updated when
// `stickyHeaderConfig.hideRelatedCell` is enabled.
const lastReportedStickyIndexRef = useRef(-1);

// State for managing layout and render updates
const [_, setLayoutTreeId] = useLayoutState(0);
Expand Down Expand Up @@ -447,7 +451,11 @@ const RecyclerViewComponent = <T,>(
if (stickyHeaderHideRelatedCell) {
setCurrentStickyIndex(newStickyHeaderIndex);
}
onChangeStickyIndex?.(newStickyHeaderIndex, currentStickyIndex);
onChangeStickyIndex?.(
newStickyHeaderIndex,
lastReportedStickyIndexRef.current
);
lastReportedStickyIndexRef.current = newStickyHeaderIndex;
}}
/>
);
Expand All @@ -462,7 +470,6 @@ const RecyclerViewComponent = <T,>(
horizontal,
recyclerViewManager,
extraData,
currentStickyIndex,
onChangeStickyIndex,
stickyHeaderHideRelatedCell,
stickyHeaderZIndex,
Expand Down
Loading