Skip to content

Commit

Permalink
[Web] Make findNodeHandle correctly handle FlatList in old API (#…
Browse files Browse the repository at this point in the history
…3361)

## Description

This PR makes `findNodeHandle` correctly recognize `FlatList` DOM element when using old API.

Fixes #3358

>[!NOTE]
> New API doesn't require this change as `FlatList` will be wrapped inside `div` with `display: contents;`

## Test plan

<details>
<summary>Tested on the following code:</summary>

```tsx
import React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import {
  FlatList,
  PanGestureHandler,
  GestureHandlerRootView,
} from 'react-native-gesture-handler';

interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

interface TodoListProps {}

const TODOS: Todo[] = [
  { id: 1, title: 'Todo 1', completed: false },
  { id: 2, title: 'Todo 2', completed: true },
  { id: 3, title: 'Todo 3', completed: false },
  { id: 4, title: 'Todo 4', completed: false },
  { id: 5, title: 'Todo 5', completed: true },
  { id: 6, title: 'Todo 6', completed: false },
  { id: 7, title: 'Todo 7', completed: false },
  { id: 8, title: 'Todo 8', completed: true },
  { id: 9, title: 'Todo 9', completed: false },
  { id: 10, title: 'Todo 10', completed: false },
  { id: 11, title: 'Todo 11', completed: true },
  { id: 12, title: 'Todo 12', completed: false },
  { id: 13, title: 'Todo 13', completed: false },
  { id: 14, title: 'Todo 14', completed: true },
  { id: 15, title: 'Todo 15', completed: false },
];

const TodoList: React.FC<TodoListProps> = () => {
  // renderItem function to render each item
  const renderItem = ({ item }: { item: Todo }) => (
    <View style={styles.item}>
      <Text style={styles.title}>
        {item.title} {item.completed ? '(completed)' : ''}
      </Text>
    </View>
  );

  return (
    <GestureHandlerRootView>
      <PanGestureHandler
        onHandlerStateChange={console.log}
        onGestureEvent={console.log}>
        <FlatList
          data={TODOS}
          renderItem={renderItem}
          keyExtractor={(item) => item.id.toString()}
        />
      </PanGestureHandler>
    </GestureHandlerRootView>
  );
};

const styles = StyleSheet.create({
  item: {
    backgroundColor: '#f9c2ff',
    padding: 20,
    marginVertical: 8,
    marginHorizontal: 16,
  },
  title: {
    fontSize: 32,
  },
});

export default TodoList;

```

</details>
  • Loading branch information
m-bert authored Jan 28, 2025
1 parent bd30677 commit e30cc63
Showing 1 changed file with 6 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/findNodeHandle.web.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { FlatList } from 'react-native';
import type { GestureHandlerRef, SVGRef } from './web/interfaces';
import { isRNSVGElement } from './web/utils';

export default function findNodeHandle(
viewRef: GestureHandlerRef | SVGRef | HTMLElement | SVGElement
): HTMLElement | SVGElement | number {
// TODO: Remove this once we remove old API.
if (viewRef instanceof FlatList) {
// @ts-ignore This is the only way to get the scroll ref from FlatList.
return viewRef._listRef._scrollRef.firstChild;
}
// Old API assumes that child handler is HTMLElement.
// However, if we nest handlers, we will get ref to another handler.
// In that case, we want to recursively call findNodeHandle with new handler viewTag (which can also be ref to another handler).
Expand Down

0 comments on commit e30cc63

Please sign in to comment.