Infinite scroll: automatically load new page of results

This commit is contained in:
James Grugett 2022-05-17 19:29:46 -04:00
parent be9df7bcd8
commit 76ffe8eea1
4 changed files with 26 additions and 22 deletions

View File

@ -4,6 +4,8 @@ import { Col } from '../layout/col'
import { SiteLink } from '../site-link'
import { ContractCard } from './contract-card'
import { ContractSearch } from '../contract-search'
import { useIsVisible } from 'web/hooks/use-is-visible'
import { useEffect, useState } from 'react'
export function ContractsGrid(props: {
contracts: Contract[]
@ -13,6 +15,16 @@ export function ContractsGrid(props: {
}) {
const { contracts, showCloseTime, hasMore, loadMore } = props
const [elem, setElem] = useState<HTMLElement | null>(null)
const isBottomVisible = useIsVisible(elem)
useEffect(() => {
console.log({ isBottomVisible, hasMore })
if (isBottomVisible) {
loadMore()
}
}, [isBottomVisible, hasMore, loadMore])
if (contracts.length === 0) {
return (
<p className="mx-2 text-gray-500">
@ -35,14 +47,7 @@ export function ContractsGrid(props: {
/>
))}
</ul>
{hasMore && (
<button
className="btn btn-primary self-center normal-case"
onClick={loadMore}
>
Show more
</button>
)}
<div ref={setElem} className="relative -top-96 h-1" />
</Col>
)
}

View File

@ -59,11 +59,11 @@ export function FeedItems(props: {
const { contract, items, className, betRowClassName } = props
const { outcomeType } = contract
const ref = useRef<HTMLDivElement | null>(null)
useSaveSeenContract(ref, contract)
const [elem, setElem] = useState<HTMLElement | null>(null)
useSaveSeenContract(elem, contract)
return (
<div className={clsx('flow-root', className)} ref={ref}>
<div className={clsx('flow-root', className)} ref={setElem}>
<div className={clsx(tradingAllowed(contract) ? '' : '-mb-6')}>
{items.map((item, activityItemIdx) => (
<div key={item.id} className={'relative pb-6'}>

View File

@ -1,11 +1,11 @@
import { RefObject, useEffect, useState } from 'react'
import { useEffect, useState } from 'react'
export function useIsVisible(elementRef: RefObject<Element>) {
return !!useIntersectionObserver(elementRef)?.isIntersecting
export function useIsVisible(element: HTMLElement | null) {
return !!useIntersectionObserver(element)?.isIntersecting
}
function useIntersectionObserver(
elementRef: RefObject<Element>
elem: HTMLElement | null
): IntersectionObserverEntry | undefined {
const [entry, setEntry] = useState<IntersectionObserverEntry>()
@ -14,16 +14,15 @@ function useIntersectionObserver(
}
useEffect(() => {
const node = elementRef?.current
const hasIOSupport = !!window.IntersectionObserver
if (!hasIOSupport || !node) return
if (!hasIOSupport || !elem) return
const observer = new IntersectionObserver(updateEntry, {})
observer.observe(node)
observer.observe(elem)
return () => observer.disconnect()
}, [elementRef])
}, [elem])
return entry
}

View File

@ -1,5 +1,5 @@
import _ from 'lodash'
import { useEffect, RefObject, useState } from 'react'
import { useEffect, useState } from 'react'
import { Contract } from 'common/contract'
import { trackView } from 'web/lib/firebase/tracking'
import { useIsVisible } from './use-is-visible'
@ -17,10 +17,10 @@ export const useSeenContracts = () => {
}
export const useSaveSeenContract = (
ref: RefObject<Element>,
elem: HTMLElement | null,
contract: Contract
) => {
const isVisible = useIsVisible(ref)
const isVisible = useIsVisible(elem)
useEffect(() => {
if (isVisible) {