Ott 337 matches lazy request (#122)
parent
bfa7a214da
commit
70d9c924f0
@ -1,15 +1,23 @@ |
||||
import React from 'react' |
||||
|
||||
import { InfiniteScroll } from 'features/InfiniteScroll' |
||||
import { Matches } from 'features/Matches' |
||||
|
||||
import { useHomePage } from './hooks' |
||||
import { Content } from './styled' |
||||
import { Content, Loading } from './styled' |
||||
|
||||
export const HomePage = () => { |
||||
const { matches } = useHomePage() |
||||
const { |
||||
fetchMoreMatches, |
||||
isFetching, |
||||
matches, |
||||
} = useHomePage() |
||||
return ( |
||||
<Content> |
||||
<Matches matches={matches} /> |
||||
<InfiniteScroll onFetchMore={fetchMoreMatches}> |
||||
<Matches matches={matches} /> |
||||
</InfiniteScroll> |
||||
{isFetching && <Loading>Loading...</Loading>} |
||||
</Content> |
||||
) |
||||
} |
||||
|
||||
@ -0,0 +1,52 @@ |
||||
import { useEffect, useRef } from 'react' |
||||
|
||||
import noop from 'lodash/noop' |
||||
|
||||
type Args = { |
||||
onIntersect: ( |
||||
target: IntersectionObserverEntry, |
||||
observer: IntersectionObserver, |
||||
) => void, |
||||
options?: IntersectionObserverInit, |
||||
} |
||||
|
||||
/** |
||||
* Хук для отслежения пересечение targetRef с rootRef |
||||
* targetRef нужно повесить на целевой элемент который будет наблюдаться, |
||||
* rootRef на корневой элемент с которым пересекается targetRef. |
||||
* Также можно проигнорить rootRef тогда по-умолчанию отслеживается |
||||
* пересечение с областью видимости документа |
||||
*/ |
||||
export const useIntersectionObserver = ({ onIntersect, options }: Args) => { |
||||
const rootRef = useRef<HTMLDivElement>(null) |
||||
const targetRef = useRef<HTMLDivElement>(null) |
||||
const rootElement = rootRef.current |
||||
const targetElement = targetRef.current |
||||
|
||||
useEffect(() => { |
||||
if (!targetElement) { |
||||
return noop |
||||
} |
||||
|
||||
const observerOptions = { root: rootElement, ...options } |
||||
const callback = ([target]: Array<IntersectionObserverEntry>) => { |
||||
if (target.isIntersecting) { |
||||
onIntersect(target, observer) |
||||
} |
||||
} |
||||
|
||||
const observer = new IntersectionObserver(callback, observerOptions) |
||||
observer.observe(targetElement) |
||||
|
||||
return () => { |
||||
observer.disconnect() |
||||
} |
||||
}, [ |
||||
rootElement, |
||||
targetElement, |
||||
onIntersect, |
||||
options, |
||||
]) |
||||
|
||||
return { rootRef, targetRef } |
||||
} |
||||
@ -0,0 +1,29 @@ |
||||
import type { ReactNode } from 'react' |
||||
import React from 'react' |
||||
|
||||
import { useIntersectionObserver } from './hooks' |
||||
import { Root, Target } from './styled' |
||||
|
||||
type Props = { |
||||
children: ReactNode, |
||||
onFetchMore: () => void, |
||||
options?: IntersectionObserverInit, |
||||
} |
||||
|
||||
export const InfiniteScroll = ({ |
||||
children, |
||||
onFetchMore, |
||||
options, |
||||
}: Props) => { |
||||
const { targetRef } = useIntersectionObserver({ |
||||
onIntersect: onFetchMore, |
||||
options, |
||||
}) |
||||
|
||||
return ( |
||||
<Root> |
||||
{children} |
||||
<Target ref={targetRef} /> |
||||
</Root> |
||||
) |
||||
} |
||||
@ -0,0 +1,8 @@ |
||||
import styled from 'styled-components/macro' |
||||
|
||||
export const Root = styled.div`` |
||||
|
||||
export const Target = styled.div` |
||||
position: relative; |
||||
bottom: 20vh; |
||||
` |
||||
Loading…
Reference in new issue