onViewableItemsChanged does not trigger when lists are conditionally displayed

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

Description

In my app, I'm navigating between two tabs containing lists of items.

After navigating, I call recordInteraction on the ref, expecting it to trigger onViewableItemsChanged
This is the documentation on recordInteraction:

Tells the list an interaction has occurred, which should trigger viewability calculations [...] This is typically called by taps on items or by navigation actions.

I added some logs to react-native's ViewabilityHelper.js when testing this and found that it exits early during the calculations because the viewable items are the same since last time. While this is technically correct, the behavior doesn't make sense, since the list wasn't visible, but now is.

I've supplied a reproducible example which behaves the same on the latest version.

Version

0.68.2

Output of npx react-native info

System:
    OS: macOS 13.0
    CPU: (8) arm64 Apple M1 Pro
    Memory: 96.86 MB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.14.2 - ~/.nvm/versions/node/v16.14.2/bin/node
    Yarn: 1.22.18 - ~/.dev/yarn/1.22.18/bin/yarn
    npm: 8.5.0 - ~/.nvm/versions/node/v16.14.2/bin/npm
    Watchman: 2022.10.17.00 - /opt/homebrew/bin/watchman
  Managers:
    CocoaPods: 1.11.3 - /Users/sam/.gem/ruby/3.1.2/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 21.4, iOS 16.0, macOS 12.3, tvOS 16.0, watchOS 9.0
    Android SDK:
      API Levels: 28, 29, 33
      Build Tools: 29.0.2, 30.0.2, 33.0.0
      System Images: android-28 | Google APIs ARM 64 v8a, android-29 | Google APIs ARM 64 v8a, android-29 | Google APIs Intel x86 Atom_64, android-30 | Google APIs ARM 64 v8a, android-31 | Google APIs ARM 64 v8a, android-33 | Google APIs ARM 64 v8a, android-33 | Google APIs Intel x86 Atom_64, android-33 | Google Play ARM 64 v8a
      Android NDK: Not Found
  IDEs:
    Android Studio: 2021.2 AI-212.5712.43.2112.8815526
    Xcode: 14.0/14A309 - /usr/bin/xcodebuild
  Languages:
    Java: 11.0.12 - /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 17.0.2 => 17.0.2
    react-native: 0.68.2 => 0.68.2
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

Steps to reproduce

  1. Conditionally render two lists
  2. Add a stable onViewableItemsChanged to both with e.g. console.log('called onViewableItemsChanged')
  3. Call recordInteraction on the respective ref after each tab-change
  4. onViewableItemsChanged is not invoked

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

import { forwardRef, useEffect, useRef, useState } from 'react';
import { Text, View, Button, FlatList, SafeAreaView } from 'react-native';

const itemsA = Array.from({ length: 50 }, (_, index) => ({
  name: `a:item:${index}`,
}));

const itemsB = Array.from({ length: 50 }, (_, index) => ({
  name: `b:item:${index}`,
}));

const onViewableItemsChanged = () => {
  console.log('called onViewableItemsChanged');
};

const Tab = forwardRef(({ items }, ref) => {
  return (
    <FlatList
      ref={ref}
      data={items}
      renderItem={({ item }) => (
        <Text style={{ padding: 20 }}>{item.name}</Text>
      )}
      onViewableItemsChanged={onViewableItemsChanged}
    />
  );
});

const TabButton = ({ title, isActive, onPress }) => {
  return (
    <View style={{ flex: 1, backgroundColor: isActive ? 'white' : '#f3f3f3' }}>
      <Button onPress={onPress} title={title} />
    </View>
  );
};

export default App = () => {
  const [activeTab, setActiveTab] = useState(1);
  const tab1Ref = useRef(null);
  const tab2Ref = useRef(null);

  useEffect(() => {
    if (activeTab === 1) {
      console.log('recording interaction for tab 1');
      tab1Ref.current.recordInteraction();
    }

    if (activeTab === 2) {
      console.log('recording interaction for tab 2');
      tab2Ref.current.recordInteraction();
    }
  }, [activeTab]);

  return (
    <SafeAreaView>
      <View style={{ flexDirection: 'row' }}>
        <TabButton
          title="Tab 1"
          isActive={activeTab === 1}
          onPress={() => setActiveTab(1)}
        />
        <TabButton
          title="Tab 2"
          isActive={activeTab === 2}
          onPress={() => setActiveTab(2)}
        />
      </View>
      {activeTab === 1 ? (
        <Tab items={itemsA} ref={tab1Ref} />
      ) : (
        <Tab items={itemsB} ref={tab2Ref} />
      )}
    </SafeAreaView>
  );
};
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-10
Star Count 106395
Watcher Count 3660
Fork Count 22685
Issue Count 2288

YOU MAY BE INTERESTED

Issue Title Created Date Comment Count Updated Date
Cronjob declaration via map 0 2022-05-05 2022-07-15
Font has no name table throw TypeError: Cannot read property 'compression' of undefined 0 2020-12-08 2022-11-25
Font file is accepted only when its not uploaded via input file 2 2020-12-29 2022-11-25
1.1 - Define Native App Container Minimum Required Feature Set 0 2022-02-09 2022-12-10
Does not recognize size 1 tuples for names in @pytest.mark.parametrize(). 1 2021-06-12 2022-04-28
Failure in win release -- "the remote name could not be resolved: 'raw.githubusercontent.com'" 1 2021-11-03 2022-10-23
MacMini M1 Compile with Make on Monterey 12.3 Beta (21E5227a) Fails to configure 2 2022-03-03 2022-07-29
host console spammed on correct+typical device close/shutdown -- I expect nothing in console 1 2022-03-05 2022-03-29
Manually add repo for appimage 1 2022-02-25 2022-10-14
async functions to not blindly await via isPromise 1 2020-08-19 2022-09-27
How are the builds done right now? 5 2020-10-06 2022-10-09
Used Sqlalchemy_utils types 2 2022-05-09 2022-11-13
Who to contact for security issues 2 2021-11-16 2022-10-09
pyrender/platforms/osmesa.py", line 19, in init_context from OpenGL.osmesa import ( ImportError: cannot import name 'OSMesaCreateContextAttribs' from 'OpenGL.osmesa' 2 2022-01-14 2022-11-26
Not able to run Algorand Studio on Apple M1 Mac Pro 3 2021-01-19 2022-10-23
Error write_gcm: can not take infinite value for swap/percent/value on machines without swap 0 2021-04-13 2022-07-07
Bug? Override aws.param.* values already in the Environment? 5 2018-09-21 2022-11-29
Enable GitHub Discussions 3 2021-02-03 2022-10-07
How did you make the update of tools like f.i. Rector? 3 2021-12-01 2022-11-17
Support the handle type in IPC 2 2021-06-15 2022-11-22
vim is blocked while editing large .vim file in an uncompleted func body 0 2022-04-04 2022-11-17
Add circular badge component 0 2021-04-10 2022-11-14
Alert dialog 1 2021-04-10 2021-12-22
Add a favicon 0 2021-04-10 2021-12-22
Month to date as a default date range 2 2021-11-02 2022-10-31
it does not enter the game, it does not show me any message. 2 2021-11-27 2022-11-24
Matrix distorted while printing 9 2022-01-18 2022-09-24
Bug report 1 2020-05-17 2022-01-20
Sub level icon is not shown in navigation 2 2022-03-08 2022-12-03
Automatic generated folders make it impossible to run different playbooks in multithreaded environment. 2 2022-10-12 2022-11-28
skills-service backwards compat build failure 1 2021-02-12 2022-11-17
Configure Portal with a certificate from user's CA 4 2021-03-03 2022-10-19
Under specific circumstances, `_get_remote_media_impl` can return `404` when it `_download_remote_file` triggers exceptions 1 2022-05-06 2022-09-26
`gl_window_make_current` is not set to override. 1 2022-01-03 2022-10-19
SVExtractTestCode is not determinstic 1 2021-10-30 2022-11-02
Bug : embedded image asset not displayed 1 2022-03-23 2022-11-08
Bump nokogiri from 1.8.2 to 1.10.4 0 2019-08-20 2022-12-10
Request to include API for vega-transforms 2 2021-05-22 2022-10-06
Per discussion on OpenZFS list, change the default for compression 1 2019-05-21 2022-11-07
groupby q7 should not decompose complex expression 3 2021-05-17 2022-12-03
Add React Native for Windows support in the portal and in the CLI 2 2021-04-29 2022-12-01
support for git diff --color-words 2 2022-08-15 2022-11-27
'dq' to close diff-split in :G not working but works when in :0Gclog 3 2022-07-29 2022-11-27
weight_initialization_exercise.ipynb exception in cell 2 2020-04-27 2022-12-04
[K3s] Update svclb networkpolicy to account for a recent change 3 2022-07-15 2022-12-07
Option to cache reduced image size to disk 7 2021-04-01 2022-09-04
[Failed CI Test] testPostRequestFormat(org.apache.helix.rest.client.TestCustomRestClient) 1 2022-08-06 2022-11-08
[Bug] The License header license-eyes fixed breaks linter rule: EXC0013 revive 4 2022-02-10 2022-11-15
Modify installation shell script to support installation of Sandbox artifacts only 1 2022-10-17 2022-12-01
[camera_web] Add support for a flash mode 1 2021-08-09 2022-12-10