ScrollableList: render emptyMessage inside the PullToRefresh
This commit is contained in:
parent
730556a692
commit
083b3c22d0
1 changed files with 51 additions and 34 deletions
|
@ -68,11 +68,26 @@ const ScrollableList: React.FC<IScrollableList> = ({
|
||||||
// const settings = useSettings();
|
// const settings = useSettings();
|
||||||
// const autoload = settings.get('autoloadMore');
|
// const autoload = settings.get('autoloadMore');
|
||||||
|
|
||||||
|
/** Normalized children */
|
||||||
|
const elements = Array.from(children || []);
|
||||||
|
|
||||||
const showPlaceholder = showLoading && Placeholder && placeholderCount > 0;
|
const showPlaceholder = showLoading && Placeholder && placeholderCount > 0;
|
||||||
const data = showPlaceholder ? Array(placeholderCount).fill('') : Array.from(children || []);
|
|
||||||
|
// NOTE: We are doing some trickery to load a feed of placeholders
|
||||||
|
// Virtuoso's `EmptyPlaceholder` unfortunately doesn't work for our use-case
|
||||||
|
const data = showPlaceholder ? Array(placeholderCount).fill('') : elements;
|
||||||
|
const isEmpty = data.length === 0; // Yes, if it has placeholders it isn't "empty"
|
||||||
|
|
||||||
|
// Add a placeholder at the bottom for loading
|
||||||
|
// (Don't use Virtuoso's `Footer` component because it doesn't preserve its height)
|
||||||
|
if (hasMore && Placeholder) {
|
||||||
|
data.push(<Placeholder />);
|
||||||
|
} else if (hasMore) {
|
||||||
|
data.push(<Spinner />);
|
||||||
|
}
|
||||||
|
|
||||||
/* Render an empty state instead of the scrollable list */
|
/* Render an empty state instead of the scrollable list */
|
||||||
const renderEmpty = () => {
|
const renderEmpty = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<div className='mt-2'>
|
<div className='mt-2'>
|
||||||
{alwaysPrepend && prepend}
|
{alwaysPrepend && prepend}
|
||||||
|
@ -88,8 +103,8 @@ const ScrollableList: React.FC<IScrollableList> = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Render the actual item */
|
/** Render a single item */
|
||||||
const renderItem = (_i: number, element: JSX.Element) => {
|
const renderItem = (_i: number, element: JSX.Element): JSX.Element => {
|
||||||
if (showPlaceholder) {
|
if (showPlaceholder) {
|
||||||
return <Placeholder />;
|
return <Placeholder />;
|
||||||
} else {
|
} else {
|
||||||
|
@ -97,40 +112,42 @@ const ScrollableList: React.FC<IScrollableList> = ({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Don't use Virtuoso's EmptyPlaceholder component so it preserves height
|
/** Render the actual Virtuoso list */
|
||||||
if (data.length === 0) {
|
const renderFeed = (): JSX.Element => (
|
||||||
return renderEmpty();
|
<Virtuoso
|
||||||
}
|
useWindowScroll
|
||||||
|
className={className}
|
||||||
|
data={data}
|
||||||
|
startReached={onScrollToTop}
|
||||||
|
endReached={onLoadMore}
|
||||||
|
isScrolling={isScrolling => isScrolling && onScroll && onScroll()}
|
||||||
|
itemContent={renderItem}
|
||||||
|
context={{
|
||||||
|
listClassName: className,
|
||||||
|
itemClassName,
|
||||||
|
}}
|
||||||
|
components={{
|
||||||
|
Header: () => prepend,
|
||||||
|
ScrollSeekPlaceholder: Placeholder as any,
|
||||||
|
EmptyPlaceholder: () => renderEmpty(),
|
||||||
|
List,
|
||||||
|
Item,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
// Don't use Virtuoso's Footer component so it preserves spacing
|
/** Conditionally render inner elements */
|
||||||
if (hasMore && Placeholder) {
|
const renderBody = (): JSX.Element => {
|
||||||
data.push(<Placeholder />);
|
if (isEmpty) {
|
||||||
} else if (hasMore) {
|
return renderEmpty();
|
||||||
data.push(<Spinner />);
|
} else {
|
||||||
}
|
return renderFeed();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PullToRefresh onRefresh={onRefresh}>
|
<PullToRefresh onRefresh={onRefresh}>
|
||||||
<Virtuoso
|
{renderBody()}
|
||||||
useWindowScroll
|
|
||||||
className={className}
|
|
||||||
data={data}
|
|
||||||
startReached={onScrollToTop}
|
|
||||||
endReached={onLoadMore}
|
|
||||||
isScrolling={isScrolling => isScrolling && onScroll && onScroll()}
|
|
||||||
itemContent={renderItem}
|
|
||||||
context={{
|
|
||||||
listClassName: className,
|
|
||||||
itemClassName,
|
|
||||||
}}
|
|
||||||
components={{
|
|
||||||
Header: () => prepend,
|
|
||||||
ScrollSeekPlaceholder: Placeholder as any,
|
|
||||||
EmptyPlaceholder: () => renderEmpty(),
|
|
||||||
List,
|
|
||||||
Item,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</PullToRefresh>
|
</PullToRefresh>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue