Commit d548122
authored
[General] Fix layout jumps with native detector (#3930)
## Description
Inside `GestureDetectorShadowNode`, we were checking whether a new
layout is available before doing any custom logic:
https://github.com/software-mansion/react-native-gesture-handler/blob/8e70b11a82fee38520761321cd67d341b2b4adf6/packages/react-native-gesture-handler/shared/shadowNodes/react/renderer/components/rngesturehandler_codegen/RNGestureHandlerDetectorShadowNode.cpp#L41-L43
However, `this->yogaNode_.getHasNewLayout()` is always `false` at this
point. `YogaLayoutableShadowNode::layout`, which goes over the child
nodes and updates their metrics, resets the flag immediately:
https://github.com/facebook/react-native/blob/490c5e8dcc6cdb19c334cc39e93a39a48ba71e96/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp#L701-L702
When visiting the detector node, the new layout information is available
in the child node but only before calling
`YogaLayoutableShadowNode::layout(layoutContext)`. If the child has no
new layout, the one from the previous revision should be reused. To
achieve that, I added a new optional value, keeping the layout metrics
from the source shadow node used to create the current revision.
## Test plan
Tested on this snipped which was able to consistently reproduce the
issue:
```jsx
import React from 'react';
import { View, StyleSheet, ScrollView, SectionList } from 'react-native';
import {
GestureHandlerRootView,
LegacySwitch,
RectButton,
Switch,
} from 'react-native-gesture-handler';
const EXAMPLES = [
{
sectionTitle: 'New api',
data: Array.from({ length: 11 }).map((_, i) => ({ id: i })),
},
];
export default function MainScreen() {
return (
<GestureHandlerRootView style={styles.container}>
<SectionList
renderScrollComponent={(props) => <ScrollView {...props} />}
sections={EXAMPLES}
ListHeaderComponent={() => (
<RectButton style={styles.autoOpenSetting}>
{/* <LegacySwitch /> */}
{/* <Switch /> */}
</RectButton>
)}
renderItem={() => <></>}
renderSectionHeader={() => <></>}
ItemSeparatorComponent={() => <View style={styles.separator} />}
/>
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 50,
},
separator: {
height: 2,
},
autoOpenSetting: {
margin: 16,
height: 50,
backgroundColor: 'red',
},
});
```1 parent 5e1605f commit d548122
2 files changed
Lines changed: 24 additions & 3 deletions
File tree
Lines changed: 17 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
37 | | - | |
38 | 37 | | |
39 | 38 | | |
40 | 39 | | |
41 | 40 | | |
42 | 41 | | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
43 | 59 | | |
44 | 60 | | |
45 | 61 | | |
46 | 62 | | |
47 | | - | |
48 | | - | |
49 | 63 | | |
50 | 64 | | |
51 | 65 | | |
| |||
Lines changed: 7 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
48 | 53 | | |
49 | 54 | | |
50 | 55 | | |
51 | 56 | | |
52 | 57 | | |
53 | 58 | | |
54 | 59 | | |
| 60 | + | |
| 61 | + | |
55 | 62 | | |
56 | 63 | | |
57 | 64 | | |
0 commit comments