[IOS] ScrollView inside FlatList blocks other touchables (children of parent Flatlist) in IOS during scroll

This issue has been created since 2022-11-14.

Description

While scrolling and clicking on any other component does not trigger any action.
A ScrollView inside FlatList blocks other clickable components (children of parent FlatList) in IOS.
This issue happens in Scrollview only when the onScroll event is used and works fine if it is not used.

Version

0.66.0, 0.69.0

Output of npx react-native info

System:
OS: macOS 12.1
CPU: (8) x64 Apple M1 Pro
Memory: 28.88 MB / 16.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 14.10.0 - ~/.nvm/versions/node/v14.10.0/bin/node
Yarn: 1.22.19 - ~/.nvm/versions/node/v14.10.0/bin/yarn
npm: 6.14.8 - ~/.nvm/versions/node/v14.10.0/bin/npm
Watchman: Not Found
Managers:
CocoaPods: 1.11.0 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 15.0, DriverKit 20.4, macOS 11.3, tvOS 15.0, watchOS 8.0
Android SDK: Not Found
IDEs:
Android Studio: 2021.2 AI-212.5712.43.2112.8815526
Xcode: 13.0/13A233 - /usr/bin/xcodebuild
Languages:
Java: 14.0.2 - /usr/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: 18.0.0 => 18.0.0
react-native: 0.69.6 => 0.69.6
react-native-macos: Not Found
npmGlobalPackages:
react-native: Not Found

Steps to reproduce

inside a parent vertical flatlist, use a horizontal child Scrollview.
While scrolling the child scrollview the other children of the parent flatlist cannot trigger onPress. They are blocked.

Snack, code example, screenshot, or link to a repository

import React, { Component } from 'react';
import { View, Text, TouchableOpacity, SafeAreaView, FlatList, ScrollView } from 'react-native';

const App = ()=> {

const renderListItem = ({ item, index }: any) => {
return (

<ScrollView
onScroll={() => {
console.log(" onScroll called scrollview");
}
}
scrollEventThrottle={16}
horizontal

      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
      <Text>selected</Text>
 
  </ScrollView>

       <TouchableOpacity
       style={{backgroundColor: 'yellow', padding: 20}}
       onPress={() =>console.log('on Press')}>
       <Text>Count</Text>

     </TouchableOpacity>
     </View>
	);
};

return (
  <SafeAreaView>
      <FlatList
        data={['']}
        renderItem={renderListItem}
        onScroll={() => {
          console.log(" onScroll called Flatlist ");
        }
      }
      />
      </SafeAreaView>
  
);

}
export default App

PratthamArora wrote this answer on 2022-11-14

Detailed RCA -

Whenever a component is clicked while the scroll is active the onPress function of the component is not being called, however components that were wrapped with touchable opacity components are highlighted i.e visible visual feedback, basically, the touch is being registered but has not been propagated to the component.
The onPress has its own life cycle. The Pressability class relies on various variables such as the current state, the previous state, and the current signal being propagated to this class to complete the entire life cycle of this method.
For onPress to be triggered, the signal that should be received is RESPONDER_RELEASE whereas in our case the signal that is received is RESPONDER_TERMINATED, which means that this event should be canceled.

The gesture recognizer system in React Native works on the Responder System wherein for a particular view to register and execute certain gestures such as a click or a swipe, the current view needs to have a lock on it i.e it needs to be the current responder for that entire page. The way the Responder System works is that it is a singleton at the global level and at one particular moment of time only one view can be the responder, hence all the other views and any gesture triggered on that view is canceled if that view is not the current responder.

One of the issues is when a scroll view is used with onScroll method defined. This is a bubbling event that is emitted from the native to the JS and for a view to consume a particular event and take action on it needs to be the responder since this event is fired every 16 ms on iOS, the scroll view is the current responder until the scrolling is stopped which cancels any other gesture triggered on any other component.

As per the entire journey defined in the Responder System, _handleScrollShouldSetResponder method is called again and again to set the scroll view as the current responder which is called in the ResponderEventPlugin from React which then triggers this method and sets the scroll view as the current responder.

Another issue is where a FlatList is nested inside a parent FlatList. It exhibits the same behavior as described above. Since a FlatList natively extends ScrollView only, it inherits the same characteristics.

After debugging the native implementations and working of ScrollView and it’s events on Android and iOS, and the lifecycle of gestures and the Responder System in React Native and React, I found that _handleScrollShouldSetResponder method is never called on Android but is called on IOS every time an OnScroll event is emitted from native to JS. This method is responsible for setting the scroll view as the current responder.

In Android whenever a Scroll Event is emitted, a boolean responderIgnoreScroll set to true is sent as metadata which is consumed in React where the transfer of responder occurs.
This flag is missing from the Scroll Event data in IOS.
Upon sending this flag with the value set to true, the _handleScrollShouldSetResponder method wasn’t called on IOS just like Android but because of this when I touch a child component of Scrollview and then drag to scroll it does not cancel the touch event and the child view becomes the responder and registers the onPress method instead of the desired behavior where the Scrollview should have scrolled.

PratthamArora wrote this answer on 2022-11-14

Related issue - #35332

PratthamArora wrote this answer on 2022-11-14

tried to use disableScrollViewPanResponder flag on my parent FlatList which does fix the issue to some level but due to this when I touch a child component of parent FlatList and then drag to scroll it does not cancel the touch event and the child view becomes the responder and registers the onPress method instead of the desired behavior where the parent FlatList should have scrolled.

PratthamArora wrote this answer on 2022-11-14

Old Reported issue - #10822

PratthamArora wrote this answer on 2022-11-20

any help on this?

More Details About Repo
Owner Name facebook
Repo Name react-native
Full Name facebook/react-native
Language JavaScript
Created Date 2015-01-09
Updated Date 2022-12-01
Star Count 106263
Watcher Count 3666
Fork Count 22655
Issue Count 2277

YOU MAY BE INTERESTED

Issue Title Created Date Comment Count Updated Date
最新 V 4.1.6 安装 提示 未检测到服务器公网ip 1 2022-10-10 2022-11-23
WhatsApp calls not working 0 2022-10-11 2022-11-23
Bug: npm install error caused by install chromium 4 2022-04-14 2022-10-12
Exclude images from being lazy-loaded only on Desktop 1 2022-06-01 2022-10-15
Incorrect result on SubArray of OffsetArray 2 2022-05-30 2022-11-06
get board data format aren't NumChan x NumDataPoint 2 2022-06-15 2022-11-24
Set Adtran terminal width to at least 132 6 2022-06-09 2022-11-25
Handle screensaver independent of X11 7 2022-09-08 2022-11-06
Gtk CRITICAL Error while trying to dockerise blueman 7 2022-09-05 2022-11-06
You ported my tabtab module over to deno 0 2021-05-04 2022-07-26
Doesn't work with react-redux v8 2 2022-04-29 2022-11-27
popInitialAction() returning null on cold start. 3 2020-12-17 2022-10-15
Still sends the search queries to bing 2 2021-12-26 2022-10-10
Unable to send email using mailkit with sendgrid in .net 5.0 2 2021-04-12 2022-11-11
Open coordinates in OM from text selection via Share menu 0 2021-09-08 2022-11-01
Clean up .zshrc 1 2021-08-17 2022-01-15
底部弹窗,输入法软键盘弹出后切换到后台在回来的时候,软键盘隐藏,但是弹窗并没有掉下来 4 2022-03-04 2022-11-25
Blog Post: The top 3 things to consider when buying cryptocurrency. 6 2021-07-05 2022-10-02
docs: clarify that `server.hmr.server` works with HTTP too 1 2021-10-01 2022-11-04
Not sustainable design for Adx proxy URL 2 2022-03-27 2022-09-28
Unable to login to Cacti Web Access and no error message 20 2022-05-05 2022-11-20
Thanos: Custom Service Types and Ingress paths blocks 2 2019-12-17 2022-11-21
Cannot upgrade past besu 22.7.2 0 2022-10-10 2022-11-22
Upgrade docker image to use latest Ubuntu 0 2022-03-27 2022-11-22
Case insensitive filenames for multisigner config files 0 2022-09-08 2022-11-22
Feature Request: Link Metadata 1 2021-08-01 2022-11-27
Android build failed 1 2022-08-04 2022-11-30
Build wont succeed on iOS in React-Native 0.69.3 commands failed: PhaseScriptExecution Xcode/DerivedData/...../Script-00DD1BFF1BD5951E006B06BC.sh (in target 'AppName' from project 'AppName') (1 failure) 1 2022-08-11 2022-09-21
Allow CLI failures (e.g. server connecting issues in build time) 2 2022-08-07 2022-09-21
Optimization problem with @sentry/react-native within a react-native-web app - lodash gots fully imported 6 2022-08-03 2022-09-21
Some Server Notice settings have no effect 8 2022-10-20 2022-11-21
Option to manually recover a tombstoned validator 1 2022-09-13 2022-09-30
Allow sorting of stream members 4 2022-03-07 2022-11-23
eas completely ignores hooks field from app.json 4 2022-01-07 2022-10-11
Remote hermes bytecode converted chunks not working. 3 2022-07-06 2022-11-20
Lich King has no phases 0 2021-11-05 2022-11-07
[Feature] Add a message when macOS blocks install 1 2022-11-16 2022-11-28
Blacklist for okapi cron jobs 1 2020-06-08 2022-11-19
Audio auto passthrough doesn't seem to work 2 2021-12-09 2022-11-26
`Exec format error` when cross compiling(v2.0.5 and v2.0.6) 7 2022-05-08 2022-10-24
jet brains rider doesn't save files to disk until build 0 2021-07-26 2022-11-18
[Bug] Typescript does not use the same trigger characters as VS Code 1 2022-10-14 2022-11-24
missing imports 2 2014-08-25 2021-11-06
SecRuleEngine logs only SecRuleID 949110 16 2022-04-21 2022-10-08
Add Renovate for `@wordpress` packages 3 2021-11-29 2022-11-12
Monitoring ticket for manual testing of Cabal library 3.6.3 (for GHC 9.2.2) candidate. 13 2022-03-03 2022-09-21
Eigenfaces with NN doesn't work 1 2017-09-14 2022-10-19
How to host an ASP Core .NET 6 application in a windows service? 5 2022-08-24 2022-08-19
Content-Length and Transfer-Encoding conflicts 7 2022-08-24 2022-10-10
ASP.NET Core 7.0 SystemTextJsonValidationMetadataProvider is inconsistent 3 2022-08-24 2022-08-30