ScrollableList: render emptyMessage inside the PullToRefresh

This commit is contained in:
Alex Gleason 2022-04-22 12:56:06 -05:00
parent 730556a692
commit 083b3c22d0
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7

View file

@ -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>
); );
}; };