Shopify/react-native-performance

FlatListPerformanceViewManager does not work correctly

dehlen opened this issue · 0 comments

Current behavior

When using a FlatListPerformanceView no callbacks are called and therefore no data is plotted in Flipper (onInteractive, onBlankArea).

Expected behavior

The callbacks should be called.

To Reproduce

Use the following versions:

"@shopify/react-native-performance": "^4.1.2",
    "@shopify/react-native-performance-lists-profiler": "^1.1.0",
    "react": "18.0.0",
    "react-native": "0.69.1",
    "react-native-flipper": "^0.142.0",

Then try to profile a list via:

<ListsProfiler
      onInteractive={(TTI) => {
        console.log(`TTI in millis: ${TTI}`);
      }}
      onBlankArea={(offsetStart, offsetEnd) => {
        console.log(`Blank area: ${Math.max(offsetStart, offsetEnd)}`);
      }}
    >
      <FlatListPerformanceView listName="MyListName">
<FlatList>...</FlatList>
</FlatListPerformanceView >
</ListsProfiler>

Platform:

  • iOS
  • Android

Packages

Which packages are affected by the issue?

  • @shopify/react-native-performance
  • @shopify/react-native-performance-lists-profiler
  • flipper-plugin-shopify-react-native-performance
  • @shopify/react-native-performance-navigation
  • @shopify/react-native-performance-navigation-bottom-tabs
  • @shopify/react-native-performance-navigation-drawer

Environment

  • I've removed the packages that I don't use
package version
@shopify/react-native-performance 4.1.2
@shopify/react-native-performance-lists-profiler 1.1.0
react-native 0.69.1

I found there are actually two issues. First when using a refreshControl in our FlatList the following property in BlankAreaView.swift is nil:

private var scrollView: UIScrollView? {
    subviews.first?.subviews.first?.subviews.first as? UIScrollView
}

This is because the view is not a subclass of UIScrollView but rather a RCTRefreshControl. When I removed the refreshControl property from our FlatList for testing purposes this property still resolved to nil since now a RTScrollContentView is returned. This is also not a subclass of UIScrollView which is why this property resolves to nil.
I fixed it for my profiling testing by changing the property to:

private var scrollView: UIScrollView? {
        guard let rctScrollView = subviews.first?.subviews.first?.subviews.first?.superview?.superview as? RCTScrollView else { return nil }
        return rctScrollView.scrollView
    }

This still does not adress the issue with the RCTRefreshControl but worked for me. You probably want to find the first RTScrollContentView class in subviews.first?.subviews.first?.subviews and from there work your way up to the UIScrollView in order to be able to register an observer for it and to ultimately call the callbacks of the ListProfiler.

Kind regards,
David