diff --git a/src/__tests__/useRecyclerViewManager.test.tsx b/src/__tests__/useRecyclerViewManager.test.tsx new file mode 100644 index 000000000..d65312447 --- /dev/null +++ b/src/__tests__/useRecyclerViewManager.test.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import { render } from "@quilted/react-testing"; + +import { FlashListProps } from "../FlashListProps"; +import { RecyclerViewManager } from "../recyclerview/RecyclerViewManager"; +import { useRecyclerViewManager } from "../recyclerview/hooks/useRecyclerViewManager"; + +const TestComponent = ({ + listProps, + onRender, +}: { + listProps: FlashListProps; + onRender: (manager: RecyclerViewManager) => void; +}) => { + const { recyclerViewManager } = useRecyclerViewManager(listProps); + onRender(recyclerViewManager); + return null; +}; + +describe("useRecyclerViewManager", () => { + it("reassigns item types when extraData changes", () => { + const data = [{ id: 1 }]; + let itemType = "standard"; + let manager: RecyclerViewManager | undefined; + const listProps: FlashListProps = { + data, + extraData: { version: 1 }, + getItemType: () => itemType, + renderItem: jest.fn(), + }; + const component = render( + { + manager = currentManager; + }} + /> + ); + + manager?.updateLayoutParams({ width: 100, height: 100 }, 0); + manager?.processDataUpdate(); + expect(Array.from(manager?.getRenderStack().values() ?? [])).toEqual([ + expect.objectContaining({ itemType: "standard" }), + ]); + + itemType = "featured"; + component.setProps({ + listProps: { + ...listProps, + extraData: { version: 2 }, + }, + }); + + expect(Array.from(manager?.getRenderStack().values() ?? [])).toEqual([ + expect.objectContaining({ itemType: "featured" }), + ]); + }); +}); diff --git a/src/recyclerview/hooks/useRecyclerViewManager.ts b/src/recyclerview/hooks/useRecyclerViewManager.ts index 5439a7b56..a075a2fe1 100644 --- a/src/recyclerview/hooks/useRecyclerViewManager.ts +++ b/src/recyclerview/hooks/useRecyclerViewManager.ts @@ -10,7 +10,7 @@ export const useRecyclerViewManager = (props: RecyclerViewProps) => { ); const [velocityTracker] = useState(() => new VelocityTracker()); - const { data } = props; + const { data, extraData } = props; useMemo(() => { recyclerViewManager.updateProps(props); @@ -19,13 +19,13 @@ export const useRecyclerViewManager = (props: RecyclerViewProps) => { }, [props]); /** - * When data changes, we need to process the data update before the render happens + * When data or extraData changes, process the layout update before render. */ useMemo(() => { recyclerViewManager.processDataUpdate(); // used to process data update so rule can be disabled // eslint-disable-next-line react-hooks/exhaustive-deps - }, [data]); + }, [data, extraData]); useEffect(() => { recyclerViewManager.restoreIfNeeded();