react-native-web icon indicating copy to clipboard operation
react-native-web copied to clipboard

ScrollView event handlers not working: onScrollBeginDrag, onScrollEndDrag, onMomentumScrollBegin, onMomentumScrollEnd

Open adithyamenu opened this issue 2 years ago • 7 comments

The problem

How to reproduce

Simplified test case: https://codesandbox.io/s/hopeful-flower-y6uf7m

Steps to reproduce:

  1. Scroll down the page
  2. Check the console for log outputs

Expected behavior

  1. The following events should be handled: onScrollBeginDrag, onScrollEndDrag, onMomentumScrollBegin, onMomentumScrollEnd.
  2. 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

adithyamenu avatar Mar 03 '22 05:03 adithyamenu

Similar issue: https://github.com/necolas/react-native-web/issues/2247

adithyamenu avatar Mar 03 '22 05:03 adithyamenu

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.

necolas avatar Jun 08 '22 21:06 necolas

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,

viveksc1994 avatar Jun 07 '23 13:06 viveksc1994

if you need onMomentumScrollEnd I found that using onScroll + a debounce handler (like this one) gave me behavior i wanted 👍

sgrund14 avatar Jun 13 '23 15:06 sgrund14

if you need onMomentumScrollEnd I found that using onScroll + a debounce handler (like this one) gave me behavior i wanted 👍

Will this work on react-vative?

SaxenaShiv avatar Jun 18 '23 18:06 SaxenaShiv

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
}

nandorojo avatar Sep 26 '23 23:09 nandorojo

For anyone looking about onScrollEnd, don't forget you can use the onTouchEnd, which is also available in View components.

lucasmaffazioli avatar Jan 19 '24 22:01 lucasmaffazioli