react-native-web
react-native-web copied to clipboard
ScrollView event handlers not working: onScrollBeginDrag, onScrollEndDrag, onMomentumScrollBegin, onMomentumScrollEnd
The problem
How to reproduce
Simplified test case: https://codesandbox.io/s/hopeful-flower-y6uf7m
Steps to reproduce:
- Scroll down the page
- Check the console for log outputs
Expected behavior
- The following events should be handled: onScrollBeginDrag, onScrollEndDrag, onMomentumScrollBegin, onMomentumScrollEnd.
- The event handlers should log outputs to the console.
Environment (include versions). Did this work in previous versions? 0.13.12
- React Native for Web (version): 0.13.12
- React (version): 16.13.1
- Browser: Chrome
Similar issue: https://github.com/necolas/react-native-web/issues/2247
This is something that those of you who need these events (aligned with what RN does with them) will need to implement and submit PRs for. I do not plan to work on adding these features myself.
Does anyone get any solution/workaround for this? Reproducible demo with a snack (expo managed workflow) - https://snack.expo.dev/@viveksc1994/flatlist-example It is showing alert while scrolling it in android/ios but not showing an alert ('onScrollBeginDrag is called') while scrolling it with the web,
if you need onMomentumScrollEnd
I found that using onScroll
+ a debounce handler (like this one) gave me behavior i wanted 👍
if you need
onMomentumScrollEnd
I found that usingonScroll
+ a debounce handler (like this one) gave me behavior i wanted 👍
Will this work on react-vative?
I only needed onMomentumScrollEnd
, so I only implemented a solution for that one. You could use the same logic to do it for others.
You can use it like this:
const webProps = useWebScrollEvents({
onMomentumScrollEnd: e => console.log(e.nativeEvent.layout)
})
return (
<ScrollView
{...webProps}
/>
)
Here's the code for useWebScrollEvents.ts
. Feel free to add support for other methods there.
/* eslint-disable react-hooks/rules-of-hooks */
import { ComponentProps, useEffect, useRef } from 'react'
import { Platform, ScrollView } from 'react-native'
const MOMENTUM_SCROLL_END_THROTTLE_MILLISECONDS = 200
export function useWebScrollEvents<
Props extends Partial<ComponentProps<typeof ScrollView>>
>(props: Props): Props {
if (Platform.OS === 'web') {
const momentumScrollEndTimer = useRef<number>()
useEffect(function cleanup() {
return () => {
clearTimeout(momentumScrollEndTimer.current)
}
}, [])
return {
...props,
onScroll(e) {
props.onScroll?.(e)
if (props.onMomentumScrollEnd) {
clearTimeout(momentumScrollEndTimer.current)
momentumScrollEndTimer.current = setTimeout(() => {
props.onMomentumScrollEnd?.(e)
}, MOMENTUM_SCROLL_END_THROTTLE_MILLISECONDS)
}
},
}
}
return props
}
For anyone looking about onScrollEnd
, don't forget you can use the onTouchEnd
, which is also available in View
components.