Commit 2e98457
authored
Remove
## Description
Since React 19 it is not necessary to use `forwardRef`. I've run `npx
eslint --fix` and it removed them, though it required some adjustments.
This PR also contains few other fixes, like not using `.Provider` in
context, or some imports which were not previously caught by linter.
## Test plan
`yarn lint-js` && `yarn ts-check`
<details>
<summary>Refs tested on the following code:</summary>
```tsx
import type { ComponentType } from 'react';
import { useRef, useState } from 'react';
import type {
FlatList as RNFlatList,
ScrollView as RNScrollView,
} from 'react-native';
import { StyleSheet, Text, View } from 'react-native';
import {
FlatList,
GestureHandlerRootView,
LegacyBaseButton,
LegacyBorderlessButton,
LegacyFlatList,
LegacyRectButton,
LegacyScrollView,
RectButton,
ScrollView,
TouchableWithoutFeedback,
} from 'react-native-gesture-handler';
import ReanimatedDrawerLayout, {
DrawerPosition,
} from 'react-native-gesture-handler/ReanimatedDrawerLayout';
const DATA = Array.from({ length: 30 }, (_, i) => ({
key: `item-${i}`,
title: `Item ${i}`,
}));
function showRef(ref: React.RefObject<unknown>) {
console.log(ref.current);
}
// ──────────────────────────────────────────────
// 1. Legacy ScrollView ref
// ──────────────────────────────────────────────
function LegacyScrollViewRefTest() {
const ref = useRef<RNScrollView>(null);
return (
<View style={styles.section}>
<Text style={styles.heading}>Legacy ScrollView ref</Text>
<RectButton style={styles.btn} onPress={() => showRef(ref)}>
<Text>Check ref</Text>
</RectButton>
<RectButton
style={styles.btn}
onPress={() => ref.current?.scrollTo({ y: 200, animated: true })}>
<Text>scrollTo(200)</Text>
</RectButton>
<LegacyScrollView ref={ref} style={styles.scrollBox}>
{DATA.map((d) => (
<Text key={d.key} style={styles.item}>
{d.title}
</Text>
))}
</LegacyScrollView>
</View>
);
}
// ──────────────────────────────────────────────
// 2. V3 ScrollView ref
// ──────────────────────────────────────────────
function V3ScrollViewRefTest() {
const ref = useRef<RNScrollView>(null);
return (
<View style={styles.section}>
<Text style={styles.heading}>V3 ScrollView ref</Text>
<RectButton style={styles.btn} onPress={() => showRef(ref)}>
<Text>Check ref</Text>
</RectButton>
<RectButton
style={styles.btn}
onPress={() => ref.current?.scrollTo({ y: 200, animated: true })}>
<Text>scrollTo(200)</Text>
</RectButton>
<ScrollView ref={ref} style={styles.scrollBox}>
{DATA.map((d) => (
<Text key={d.key} style={styles.item}>
{d.title}
</Text>
))}
</ScrollView>
</View>
);
}
// ──────────────────────────────────────────────
// 3. Legacy FlatList ref
// ──────────────────────────────────────────────
function LegacyFlatListRefTest() {
const ref = useRef<RNFlatList>(null);
return (
<View style={styles.section}>
<Text style={styles.heading}>Legacy FlatList ref</Text>
<RectButton style={styles.btn} onPress={() => showRef(ref)}>
<Text>Check ref</Text>
</RectButton>
<RectButton
style={styles.btn}
onPress={() =>
ref.current?.scrollToIndex({ index: 10, animated: true })
}>
<Text>scrollToIndex(10)</Text>
</RectButton>
<LegacyFlatList
ref={ref}
style={styles.scrollBox}
data={DATA}
renderItem={({ item }) => <Text style={styles.item}>{item.title}</Text>}
/>
</View>
);
}
// ──────────────────────────────────────────────
// 4. V3 FlatList ref
// ──────────────────────────────────────────────
function V3FlatListRefTest() {
const ref = useRef<RNFlatList>(null);
return (
<View style={styles.section}>
<Text style={styles.heading}>V3 FlatList ref</Text>
<RectButton style={styles.btn} onPress={() => showRef(ref)}>
<Text>Check ref</Text>
</RectButton>
<RectButton
style={styles.btn}
onPress={() =>
ref.current?.scrollToIndex({ index: 10, animated: true })
}>
<Text>scrollToIndex(10)</Text>
</RectButton>
<FlatList
ref={ref}
style={styles.scrollBox}
data={DATA}
renderItem={({ item }) => <Text style={styles.item}>{item.title}</Text>}
/>
</View>
);
}
// ──────────────────────────────────────────────
// 5. Legacy Buttons refs
// ──────────────────────────────────────────────
function LegacyButtonRefsTest() {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const baseRef = useRef<ComponentType<any>>(null);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const rectRef = useRef<ComponentType<any>>(null);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const borderlessRef = useRef<ComponentType<any>>(null);
return (
<View style={styles.section}>
<Text style={styles.heading}>Legacy Button refs</Text>
<LegacyBaseButton
ref={baseRef}
style={styles.btn}
onPress={() => showRef(baseRef)}>
<Text>BaseButton - tap to check ref</Text>
</LegacyBaseButton>
<LegacyRectButton
ref={rectRef}
style={styles.btn}
onPress={() => showRef(rectRef)}>
<Text>RectButton - tap to check ref</Text>
</LegacyRectButton>
<LegacyBorderlessButton
ref={borderlessRef}
style={styles.btn}
onPress={() => showRef(borderlessRef)}>
<Text>BorderlessButton - tap to check ref</Text>
</LegacyBorderlessButton>
</View>
);
}
// ──────────────────────────────────────────────
// 6. TouchableWithoutFeedback ref
// ──────────────────────────────────────────────
function TouchableRefTest() {
const ref = useRef(null);
return (
<View style={styles.section}>
<Text style={styles.heading}>TouchableWithoutFeedback ref</Text>
<TouchableWithoutFeedback ref={ref} onPress={() => showRef(ref)}>
<View style={styles.btn}>
<Text>Tap to check ref</Text>
</View>
</TouchableWithoutFeedback>
</View>
);
}
// ──────────────────────────────────────────────
// 7. DrawerLayout ref (imperative open/close)
// ──────────────────────────────────────────────
function DrawerLayoutRefTest() {
const drawerRef =
useRef<React.ComponentRef<typeof ReanimatedDrawerLayout>>(null);
return (
<View style={styles.section}>
<Text style={styles.heading}>DrawerLayout ref</Text>
<RectButton style={styles.btn} onPress={() => showRef(drawerRef)}>
<Text>Check ref</Text>
</RectButton>
<RectButton
style={styles.btn}
onPress={() => drawerRef.current?.openDrawer()}>
<Text>Open drawer</Text>
</RectButton>
<ReanimatedDrawerLayout
ref={drawerRef}
drawerWidth={200}
drawerPosition={DrawerPosition.LEFT}
renderNavigationView={() => (
<View style={styles.drawer}>
<Text style={styles.heading}>Drawer content</Text>
<RectButton
style={styles.btn}
onPress={() => drawerRef.current?.closeDrawer()}>
<Text>Close drawer</Text>
</RectButton>
</View>
)}>
<View style={styles.drawerContent}>
<Text>Main content - swipe right to open</Text>
</View>
</ReanimatedDrawerLayout>
</View>
);
}
// ──────────────────────────────────────────────
// 8. Callback ref test
// ──────────────────────────────────────────────
function CallbackRefTest() {
const [status, setStatus] = useState('waiting...');
return (
<View style={styles.section}>
<Text style={styles.heading}>Callback ref</Text>
<Text>ScrollView callback ref: {status}</Text>
<ScrollView
ref={(node) => {
setStatus(node ? 'OK' : 'NULL');
}}
style={styles.scrollBox}>
{DATA.slice(0, 5).map((d) => (
<Text key={d.key} style={styles.item}>
{d.title}
</Text>
))}
</ScrollView>
</View>
);
}
// ──────────────────────────────────────────────
// Main app
// ──────────────────────────────────────────────
export default function App() {
return (
<GestureHandlerRootView style={styles.root}>
<ScrollView
style={styles.container}
contentContainerStyle={styles.content}>
<Text style={styles.title}>Ref Reproduction Tests</Text>
<Text style={styles.subtitle}>
Tap "Check ref" buttons - expect OK, not NULL.{'\n'}
Test scrollTo / scrollToIndex to verify imperative methods.
</Text>
<LegacyScrollViewRefTest />
<V3ScrollViewRefTest />
<LegacyFlatListRefTest />
<V3FlatListRefTest />
<LegacyButtonRefsTest />
<TouchableRefTest />
<DrawerLayoutRefTest />
<CallbackRefTest />
</ScrollView>
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
root: { flex: 1, backgroundColor: '#f5f5f5' },
container: { flex: 1 },
content: { padding: 16, paddingBottom: 80 },
title: { fontSize: 22, fontWeight: 'bold', color: '#333', marginBottom: 4 },
subtitle: { fontSize: 13, color: '#666', marginBottom: 16 },
section: {
marginBottom: 24,
backgroundColor: '#fff',
borderRadius: 12,
padding: 12,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 3,
elevation: 2,
},
heading: { fontSize: 16, fontWeight: '600', color: '#333', marginBottom: 8 },
btn: {
backgroundColor: '#e8e8ff',
padding: 10,
borderRadius: 8,
marginBottom: 8,
alignItems: 'center' as const,
},
scrollBox: { height: 120, backgroundColor: '#fafafa', borderRadius: 8 },
item: { padding: 10, borderBottomWidth: 1, borderBottomColor: '#eee' },
drawer: { flex: 1, backgroundColor: '#dde', padding: 16 },
drawerContent: {
flex: 1,
justifyContent: 'center' as const,
alignItems: 'center' as const,
minHeight: 150,
},
});
```
</details>forwardRef (#4093)1 parent 59983a5 commit 2e98457
15 files changed
Lines changed: 507 additions & 527 deletions
File tree
- apps
- basic-example
- common-app
- expo-example
- macos-example
- packages/react-native-gesture-handler/src
- components
- touchables
- handlers
- gestures/GestureDetector
- v3/components
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
3 | | - | |
4 | | - | |
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
9 | 12 | | |
10 | 13 | | |
11 | 14 | | |
12 | 15 | | |
13 | 16 | | |
14 | 17 | | |
15 | | - | |
16 | 18 | | |
17 | 19 | | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | 20 | | |
22 | | - | |
23 | 21 | | |
24 | 22 | | |
| 23 | + | |
| 24 | + | |
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
5 | 7 | | |
6 | 8 | | |
7 | 9 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
Lines changed: 4 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
147 | 147 | | |
148 | 148 | | |
149 | 149 | | |
150 | | - | |
| 150 | + | |
151 | 151 | | |
152 | 152 | | |
153 | 153 | | |
154 | 154 | | |
155 | 155 | | |
156 | 156 | | |
157 | | - | |
| 157 | + | |
158 | 158 | | |
159 | 159 | | |
160 | 160 | | |
| |||
228 | 228 | | |
229 | 229 | | |
230 | 230 | | |
231 | | - | |
| 231 | + | |
232 | 232 | | |
233 | 233 | | |
234 | 234 | | |
| |||
276 | 276 | | |
277 | 277 | | |
278 | 278 | | |
279 | | - | |
| 279 | + | |
280 | 280 | | |
281 | 281 | | |
282 | 282 | | |
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
95 | 95 | | |
96 | 96 | | |
97 | 97 | | |
98 | | - | |
| 98 | + | |
99 | 99 | | |
100 | 100 | | |
101 | 101 | | |
| |||
Lines changed: 18 additions & 23 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
3 | | - | |
4 | | - | |
5 | | - | |
6 | | - | |
| 1 | + | |
7 | 2 | | |
8 | 3 | | |
9 | 4 | | |
| |||
49 | 44 | | |
50 | 45 | | |
51 | 46 | | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
56 | 53 | | |
57 | 54 | | |
58 | 55 | | |
59 | 56 | | |
60 | 57 | | |
61 | 58 | | |
62 | | - | |
63 | | - | |
64 | 59 | | |
65 | 60 | | |
66 | 61 | | |
| |||
73 | 68 | | |
74 | 69 | | |
75 | 70 | | |
76 | | - | |
| 71 | + | |
77 | 72 | | |
78 | 73 | | |
79 | 74 | | |
| |||
112 | 107 | | |
113 | 108 | | |
114 | 109 | | |
115 | | - | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
116 | 118 | | |
117 | 119 | | |
118 | 120 | | |
| |||
135 | 137 | | |
136 | 138 | | |
137 | 139 | | |
138 | | - | |
139 | 140 | | |
140 | 141 | | |
141 | 142 | | |
| |||
157 | 158 | | |
158 | 159 | | |
159 | 160 | | |
160 | | - | |
161 | | - | |
162 | | - | |
163 | | - | |
164 | | - | |
165 | | - | |
166 | | - | |
167 | | - | |
| 161 | + | |
| 162 | + | |
168 | 163 | | |
169 | 164 | | |
170 | 165 | | |
Lines changed: 7 additions & 10 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
63 | 60 | | |
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
| 16 | + | |
17 | 17 | | |
18 | | - | |
| 18 | + | |
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| |||
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
| 16 | + | |
17 | 17 | | |
18 | | - | |
| 18 | + | |
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| |||
0 commit comments