Skip to content
Merged
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
2 changes: 2 additions & 0 deletions src/components/react-virtualized-helpers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as withInfiniteLoader } from './withInfiniteLoader';
export type { InfiniteLoaderConfig, WithInfiniteLoaderProps } from './withInfiniteLoader';
66 changes: 66 additions & 0 deletions src/components/react-virtualized-helpers/withInfiniteLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import * as React from 'react';
import InfiniteLoader from '@box/react-virtualized/dist/commonjs/InfiniteLoader';

/** A single row index, as passed to `isRowLoaded`. */
interface Index {
index: number;
}

/** An inclusive range of row indices, as passed to `loadMoreRows` and `onRowsRendered`. */
interface IndexRange {
startIndex: number;
stopIndex: number;
}

type OnRowsRendered = (params: IndexRange) => void;

type WithOnRowsRendered = {
onRowsRendered?: OnRowsRendered;
};

function getDisplayName(WrappedComponent: React.ComponentClass<WithOnRowsRendered>) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}

export interface InfiniteLoaderConfig {
/** Returns a truthy value when the requested row has loaded. */
isRowLoaded: (params: Index) => unknown;
/** Callback invoked when more rows must be loaded. Its result may resolve after loading finishes. */
loadMoreRows: (params: IndexRange) => PromiseLike<unknown> | void;
/** Minimum number of rows to load in each batch. */
minimumBatchSize?: number;
/** Total number of rows in the list. */
rowCount: number;
/** Number of rows from the rendered range at which to start loading. */
threshold?: number;
}

Comment thread
bonchevskyi marked this conversation as resolved.
export interface WithInfiniteLoaderProps {
/** Configuration passed to the react-virtualized InfiniteLoader. */
infiniteLoaderProps: InfiniteLoaderConfig;
}

function withInfiniteLoader<P extends WithOnRowsRendered>(WrappedComponent: React.ComponentClass<P>) {
const InfiniteLoaderComponent = ({
infiniteLoaderProps: { isRowLoaded, loadMoreRows, minimumBatchSize, rowCount, threshold },
...rest
}: WithInfiniteLoaderProps & Omit<P, keyof WithOnRowsRendered>) => (
<InfiniteLoader
isRowLoaded={isRowLoaded}
loadMoreRows={loadMoreRows}
minimumBatchSize={minimumBatchSize}
rowCount={rowCount}
threshold={threshold}
>
{({ onRowsRendered, registerChild }) => (
<WrappedComponent {...(rest as unknown as P)} ref={registerChild} onRowsRendered={onRowsRendered} />
)}
</InfiniteLoader>
);

InfiniteLoaderComponent.displayName = `WithInfiniteLoader(${getDisplayName(WrappedComponent)})`;

return InfiniteLoaderComponent;
}

export default withInfiniteLoader;
Loading