Skip to content
Closed
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
49 changes: 49 additions & 0 deletions src/__tests__/FixedSizeGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ReactTestRenderer from 'react-test-renderer';
import ReactTestUtils from 'react-dom/test-utils';
import { FixedSizeGrid } from '..';
import * as domHelpers from '../domHelpers';
import { defaultCellRangeRenderer } from '../createGridComponent';

const findScrollContainer = rendered => rendered.root.children[0].children[0];

Expand Down Expand Up @@ -1085,4 +1086,52 @@ describe('FixedSizeGrid', () => {
);
});
});

describe('cellRangeRenderer', () => {
it('should use a custom cellRangeRenderer if specified', () => {
const width = 90;
const height = 70;
const columnWidth = 20;
const rowHeight = 40;
const overscanRowsCount = 1;
const overscanColumnsCount = 1;

const expectedColumnStopIndex = Math.floor(
width / columnWidth + overscanColumnsCount
);

const expectedRowStopIndex = Math.floor(
height / rowHeight + overscanRowsCount
);

const CustomRow = props => <div {...props} />;
const cellRangeRenderer = jest
.fn()
.mockImplementation(defaultCellRangeRenderer);

const rendered = ReactTestRenderer.create(
<FixedSizeGrid
{...defaultProps}
{...{
width,
height,
columnWidth,
rowHeight,
overscanRowsCount,
overscanColumnsCount,
}}
cellRangeRenderer={cellRangeRenderer}
/>
);

expect(cellRangeRenderer).toHaveBeenCalledTimes(1);
expect(cellRangeRenderer).toHaveBeenCalledWith({
columnStartIndex: 0,
rowStartIndex: 0,
columnStopIndex: expectedColumnStopIndex,
rowStopIndex: expectedRowStopIndex,
childFactory: expect.any(Function),
});
});
});
});
35 changes: 35 additions & 0 deletions src/__tests__/FixedSizeList.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import ReactDOM from 'react-dom';
import ReactTestRenderer from 'react-test-renderer';
import ReactTestUtils from 'react-dom/test-utils';
import { FixedSizeList } from '..';
import { defaultRowRangeRenderer } from '../createListComponent';

const simulateScroll = (instance, scrollOffset, direction = 'vertical') => {
if (direction === 'horizontal') {
Expand Down Expand Up @@ -870,4 +871,38 @@ describe('FixedSizeList', () => {
);
});
});

describe('rowRangeRenderer', () => {
it('should use a custom rowRangeRenderer if specified', () => {
const height = 70;
const itemSize = 40;
const overscanCount = 1;

const expectedStopIndex = Math.floor(height / itemSize + overscanCount);

const CustomRow = props => <div {...props} />;
const rowRangeRenderer = jest
.fn()
.mockImplementation(defaultRowRangeRenderer);

const rendered = ReactTestRenderer.create(
<FixedSizeList
{...defaultProps}
{...{
height,
itemSize,
overscanCount,
}}
rowRangeRenderer={rowRangeRenderer}
/>
);

expect(rowRangeRenderer).toHaveBeenCalledTimes(1);
expect(rowRangeRenderer).toHaveBeenCalledWith({
startIndex: 0,
stopIndex: expectedStopIndex,
childFactory: expect.any(Function),
});
});
});
});
49 changes: 49 additions & 0 deletions src/__tests__/VariableSizeGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Simulate } from 'react-dom/test-utils';
import ReactTestRenderer from 'react-test-renderer';
import { VariableSizeGrid } from '..';
import * as domHelpers from '../domHelpers';
import { defaultCellRangeRenderer } from '../createGridComponent';

const simulateScroll = (instance, { scrollLeft, scrollTop }) => {
instance._outerRef.scrollLeft = scrollLeft;
Expand Down Expand Up @@ -584,4 +585,52 @@ describe('VariableSizeGrid', () => {
expect(innerRef.current.style.height).toEqual('106px');
expect(innerRef.current.style.width).toEqual('101px');
});

describe('cellRangeRenderer', () => {
it('should use a custom cellRangeRenderer if specified', () => {
const width = 90;
const height = 70;
const columnWidth = _ => 20;
const rowHeight = _ => 40;
const overscanRowsCount = 1;
const overscanColumnsCount = 1;

const expectedColumnStopIndex = Math.floor(
width / columnWidth() + overscanColumnsCount
);

const expectedRowStopIndex = Math.floor(
height / rowHeight() + overscanRowsCount
);

const CustomRow = props => <div {...props} />;
const cellRangeRenderer = jest
.fn()
.mockImplementation(defaultCellRangeRenderer);

const rendered = ReactTestRenderer.create(
<VariableSizeGrid
{...defaultProps}
{...{
width,
height,
columnWidth,
rowHeight,
overscanRowsCount,
overscanColumnsCount,
}}
cellRangeRenderer={cellRangeRenderer}
/>
);

expect(cellRangeRenderer).toHaveBeenCalledTimes(1);
expect(cellRangeRenderer).toHaveBeenCalledWith({
columnStartIndex: 0,
rowStartIndex: 0,
columnStopIndex: expectedColumnStopIndex,
rowStopIndex: expectedRowStopIndex,
childFactory: expect.any(Function),
});
});
});
});
35 changes: 35 additions & 0 deletions src/__tests__/VariableSizeList.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { render } from 'react-dom';
import { Simulate } from 'react-dom/test-utils';
import ReactTestRenderer from 'react-test-renderer';
import { VariableSizeList } from '..';
import { defaultRowRangeRenderer } from '../createListComponent';

const simulateScroll = (instance, scrollOffset, direction = 'vertical') => {
if (direction === 'horizontal') {
Expand Down Expand Up @@ -349,4 +350,38 @@ describe('VariableSizeList', () => {
instance.setState({ itemCount: 3 });
expect(innerRef.current.style.height).toEqual('78px');
});

describe('rowRangeRenderer', () => {
it('should use a custom rowRangeRenderer if specified', () => {
const height = 70;
const itemSize = _ => 40;
const overscanCount = 1;

const expectedStopIndex = Math.floor(height / itemSize() + overscanCount);

const CustomRow = props => <div {...props} />;
const rowRangeRenderer = jest
.fn()
.mockImplementation(defaultRowRangeRenderer);

const rendered = ReactTestRenderer.create(
<VariableSizeList
{...defaultProps}
{...{
height,
itemSize,
overscanCount,
}}
rowRangeRenderer={rowRangeRenderer}
/>
);

expect(rowRangeRenderer).toHaveBeenCalledTimes(1);
expect(rowRangeRenderer).toHaveBeenCalledWith({
startIndex: 0,
stopIndex: expectedStopIndex,
childFactory: expect.any(Function),
});
});
});
});
82 changes: 59 additions & 23 deletions src/createGridComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,23 @@ type OnScrollCallback = ({
type ScrollEvent = SyntheticEvent<HTMLDivElement>;
type ItemStyleCache = { [key: string]: Object };

type CellRangeRendererParams<T> = {|
columnStartIndex: number,
columnStopIndex: number,
rowStartIndex: number,
rowStopIndex: number,
childFactory: (params: {|
rowIndex: number,
columnIndex: number,
|}) => React$Element<RenderComponent<T>>,
|};

type CellRangeRenderer<T> = (
params: CellRangeRendererParams<T>
) => React$Element<RenderComponent<T>>[];

export type Props<T> = {|
cellRangeRenderer?: CellRangeRenderer<T>,
children: RenderComponent<T>,
className?: string,
columnCount: number,
Expand Down Expand Up @@ -127,6 +143,26 @@ const IS_SCROLLING_DEBOUNCE_INTERVAL = 150;
const defaultItemKey = ({ columnIndex, data, rowIndex }) =>
`${rowIndex}:${columnIndex}`;

export function defaultCellRangeRenderer<T>({
rowStartIndex,
rowStopIndex,
columnStartIndex,
columnStopIndex,
childFactory,
}: CellRangeRendererParams<T>): React$Element<RenderComponent<T>>[] {
const items = [];
for (let rowIndex = rowStartIndex; rowIndex <= rowStopIndex; rowIndex++) {
for (
let columnIndex = columnStartIndex;
columnIndex <= columnStopIndex;
columnIndex++
) {
items.push(childFactory({ rowIndex, columnIndex }));
}
}
return items;
}

// In DEV mode, this Set helps us only log a warning once per component instance.
// This avoids spamming the console every time a render happens.
let devWarningsOverscanCount = null;
Expand Down Expand Up @@ -348,6 +384,7 @@ export default function createGridComponent({

render() {
const {
cellRangeRenderer = (defaultCellRangeRenderer: CellRangeRenderer<T>),
children,
className,
columnCount,
Expand All @@ -373,30 +410,29 @@ export default function createGridComponent({
] = this._getHorizontalRangeToRender();
const [rowStartIndex, rowStopIndex] = this._getVerticalRangeToRender();

const items = [];
const resolvedIsScrolling = useIsScrolling ? isScrolling : undefined;

const childFactory = ({ rowIndex, columnIndex }) => {
return createElement(children, {
columnIndex,
data: itemData,
isScrolling: resolvedIsScrolling,
key: itemKey({ columnIndex, data: itemData, rowIndex }),
rowIndex,
style: this._getItemStyle(rowIndex, columnIndex),
});
};

let items = [];

if (columnCount > 0 && rowCount) {
for (
let rowIndex = rowStartIndex;
rowIndex <= rowStopIndex;
rowIndex++
) {
for (
let columnIndex = columnStartIndex;
columnIndex <= columnStopIndex;
columnIndex++
) {
items.push(
createElement(children, {
columnIndex,
data: itemData,
isScrolling: useIsScrolling ? isScrolling : undefined,
key: itemKey({ columnIndex, data: itemData, rowIndex }),
rowIndex,
style: this._getItemStyle(rowIndex, columnIndex),
})
);
}
}
items = cellRangeRenderer({
rowStartIndex,
rowStopIndex,
columnStartIndex,
columnStopIndex,
childFactory,
});
}

// Read this value AFTER items have been created,
Expand Down
Loading