まえがき
ライブラリ作るほどでもないけど毎回コード書くのも面倒なので、リファレンス的な目的でcustom hookをべたっと貼りました。ScrollViewをラップしてRenderPropにしちゃってもOK。
用途は
- 下に一定スクロールしたら消え、上にスクロールすると戻るヘッダ(exampleはこれ)
- 下に一定スクロールするとXXする何か
- 一番下にスクロールしたら追加ロード
- などなど
結論
こんな感じで便利Custom hookを作って、、、
import { useRef, useCallback } from 'react'
import { NativeSyntheticEvent, NativeScrollEvent } from 'react-native'
export function useScroll({
onScrollUp,
onScrollDown,
onScrollRight,
onScrollLeft,
onScrollToBottom,
}: {
onScrollUp?: (offsetY: number) => void
onScrollDown?: (offsetY: number) => void
onScrollRight?: (offsetX: number) => void
onScrollLeft?: (offsetX: number) => void
onScrollToBottom?: () => void
}) {
const offset = useRef({ x: 0, y: 0 })
const onScroll = useCallback(
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
const { nativeEvent } = event
const diffY = nativeEvent.contentOffset.y - offset.current.y
const diffX = nativeEvent.contentOffset.x - offset.current.x
if (onScrollDown && diffY > 0) {
onScrollDown(diffY)
}
if (onScrollUp && diffY < 0) {
onScrollUp(diffY)
}
if (onScrollRight && diffX > 0) {
onScrollRight(diffX)
}
if (onScrollLeft && diffX < 0) {
onScrollLeft(diffX)
}
if (
onScrollToBottom &&
nativeEvent.layoutMeasurement.height + nativeEvent.contentOffset.y >=
nativeEvent.contentSize.height
) {
onScrollToBottom()
}
},
[onScrollDown, onScrollLeft, onScrollRight, onScrollToBottom, onScrollUp]
)
const onScrollBeginDrag = useCallback(
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
const { nativeEvent } = event
offset.current = nativeEvent.contentOffset
},
[]
)
return {
onScroll,
onScrollBeginDrag,
}
}
あとはScrollViewを使ってる画面で使うだけ。
const THREASHOLD = 50
function SampleApp() {
const [isHeaderActive, toggleHeader] = useState(true)
const { onScroll, onScrollBeginDrag } = useScroll({
onScrollDown: offsetY => {
if (offsetY >= THREASHOLD) {
toggleHeader(false)
}
},
onScrollUp: () => {
toggleHeader(true)
},
})
return (
<ScrollView
onScroll={onScroll}
onScrollBeginDrag={onScrollBeginDrag}
>
{ isHeaderActive && <HeaderComponent /> }
</ScrollView>
)
}