infinite scroll support
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { bMessenger } from 'src/shared/messages';
|
||||
import { Course } from 'src/shared/types/Course';
|
||||
import useInfiniteScroll from '../hooks/useInfiniteScroll';
|
||||
import { populateSearchInputs } from '../lib/courseCatalog/populateSearchInputs';
|
||||
import { SiteSupport } from '../lib/getSiteSupport';
|
||||
import { Button } from './common/Button/Button';
|
||||
@@ -17,6 +17,13 @@ export default function CourseCatalogMain({ support }: Props) {
|
||||
const [rows, setRows] = React.useState<HTMLTableRowElement[]>([]);
|
||||
const [selectedCourse, setSelectedCourse] = React.useState<Course | null>(null);
|
||||
|
||||
const [shouldHighlight, setShouldHighlight] = React.useState(false);
|
||||
|
||||
const isInfiniteScrollLoading = useInfiniteScroll(async () => {
|
||||
console.log('infinite scroll');
|
||||
return false;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
populateSearchInputs();
|
||||
}, []);
|
||||
@@ -29,24 +36,42 @@ export default function CourseCatalogMain({ support }: Props) {
|
||||
return (
|
||||
<div>
|
||||
<TableHead />
|
||||
<Button onClick={() => setRows([])}>{shouldHighlight ? 'Unhighlight' : 'Highlight'}</Button>
|
||||
{rows.map(row => (
|
||||
<TableRow key={row.id} row={row} />
|
||||
<TableRow row={row} shouldHighlight={shouldHighlight} />
|
||||
))}
|
||||
{isInfiniteScrollLoading && <div>Scrolling...</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const TableRow: (props: { row: HTMLTableRowElement }) => JSX.Element | null = ({ row }) => {
|
||||
const TableRow: (props: { row: HTMLTableRowElement; shouldHighlight: boolean }) => JSX.Element | null = ({
|
||||
row,
|
||||
shouldHighlight,
|
||||
}) => {
|
||||
const [portalContainer, setPortalContainer] = React.useState<HTMLTableCellElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const portalContainer = document.createElement('td');
|
||||
portalContainer.setAttribute('id', 'ut-registration-plus-table-row-portal');
|
||||
const lastTableCell = row.querySelector('td:last-child');
|
||||
lastTableCell!.after(portalContainer);
|
||||
setPortalContainer(portalContainer);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('shouldHighlight', shouldHighlight);
|
||||
// make the color of the row change when the button is clicked
|
||||
if (shouldHighlight) {
|
||||
row.querySelectorAll('td').forEach(td => {
|
||||
td.style.color = 'red';
|
||||
});
|
||||
} else {
|
||||
row.querySelectorAll('td').forEach(td => {
|
||||
td.style.color = '';
|
||||
});
|
||||
}
|
||||
}, [shouldHighlight, row]);
|
||||
|
||||
if (!portalContainer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
38
src/views/hooks/useInfiniteScroll.ts
Normal file
38
src/views/hooks/useInfiniteScroll.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { sleep } from 'src/shared/util/time';
|
||||
|
||||
/**
|
||||
* Hook to execute a callback when the user scrolls to the bottom of the page
|
||||
* @param callback the function to be called when the user scrolls to the bottom of the page
|
||||
* @returns isLoading boolean to indicate if the callback is currently being executed
|
||||
*/
|
||||
|
||||
export default function useInfiniteScroll(callback: () => Promise<boolean>): boolean {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('scroll', isScrolling);
|
||||
return () => window.removeEventListener('scroll', isScrolling);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoading) return;
|
||||
callback().then(isFinished => {
|
||||
if (!isFinished) {
|
||||
sleep(1000).then(() => {
|
||||
setIsLoading(false);
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [isLoading]);
|
||||
|
||||
function isScrolling() {
|
||||
if (
|
||||
window.innerHeight + document.documentElement.scrollTop !== document.documentElement.offsetHeight ||
|
||||
isLoading
|
||||
)
|
||||
return;
|
||||
setIsLoading(true);
|
||||
}
|
||||
return isLoading;
|
||||
}
|
||||
Reference in New Issue
Block a user