react-native: [ScrollView] Children in a ScrollView don't always cancel touches when the ScrollView is scrolling

When scrolling through a ListView with lots of content, sometimes it is possible to trigger the onPress event of a Touchable row. The ListView keeps on scrolling while the onPress handler runs.

(In our code, the resulting UX is janky for a few reasons: 1/ this usually happens when new list rows are being rendered, so the UI is already a little choppy, 2/ the onPress handler in our case pushes a new route onto the Navigator stack, so it’s trying to smoothly animate the scene transition, 3/ the ListView keeps on scrolling with inertia so you lose your position in the feed when you navigate back to it, 4/ because the ListView is scrolling and rendering new rows, that adds jank to the Navigator’s ongoing transition.)

It seems to occur when the app chokes (not quite sure which thread). I suspect the JS doesn’t learn that the ScrollView has begun scrolling, so it lets the Touchable component handle the press.

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 36 (14 by maintainers)

Most upvoted comments

There is a dirty way that I’ve found to bypass this case temporarily:

var _listViewDirtyPressEnabled = true;
<ListView 
    onTouchMove={(e)=>{
        _listViewDirtyPressEnabled = false;
    }}
    onTouchEnd={(e)=>{
        _listViewDirtyPressEnabled = true;
    }}
    renderRow={(rowData)=>{
        return (
            <TouchableOpacity
                onPress={()=>{
                    if( !_listViewDirtyPressEnabled ) return ;

                    //other...
                }}
            > 
                <RowItem rowData={rowData} />
            </TouchableOpacity>
        );
    }}
/>

But looking forward to real solutions.