Skip to content

Commit 1473f39

Browse files
authored
[Native] Fix native GestureDetector zIndex handling (#4257)
## Description Fixes #4254 Fabric computes view ordering from each shadow node’s orderIndex, which React Native derives from zIndex. Since RNGH v3 inserts an RNGestureHandlerDetector shadow node between the parent and the actual child view, the parent was sorting the detector instead of the styled child. The detector kept the default order index, so components like v3 Pressable did not respect zIndex. This PR makes RNGestureHandlerDetectorShadowNode mirror its single child’s RN-computed order index. For multi-child detectors, it keeps neutral ordering because no single detector order index can accurately represent multiple children with independent zIndex values. ## Test plan Test reproducer from the issue
1 parent 9938977 commit 1473f39

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

packages/react-native-gesture-handler/shared/shadowNodes/react/renderer/components/rngesturehandler_codegen/RNGestureHandlerDetectorShadowNode.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,14 @@ void RNGestureHandlerDetectorShadowNode::initialize() {
2929
// Will clone the child and ensure it's not flattened
3030
replaceChild(*children[i], children[i], i);
3131
}
32+
33+
updateOrderIndexFromChildren();
3234
}
3335

3436
void RNGestureHandlerDetectorShadowNode::appendChild(
3537
const std::shared_ptr<const ShadowNode> &child) {
3638
YogaLayoutableShadowNode::appendChild(unflattenNode(child));
39+
updateOrderIndexFromChildren();
3740
}
3841

3942
void RNGestureHandlerDetectorShadowNode::replaceChild(
@@ -42,6 +45,7 @@ void RNGestureHandlerDetectorShadowNode::replaceChild(
4245
size_t suggestedIndex) {
4346
YogaLayoutableShadowNode::replaceChild(
4447
oldChild, unflattenNode(newChild), suggestedIndex);
48+
updateOrderIndexFromChildren();
4549
}
4650

4751
void RNGestureHandlerDetectorShadowNode::layout(LayoutContext layoutContext) {
@@ -127,4 +131,19 @@ RNGestureHandlerDetectorShadowNode::unflattenNode(
127131
return clonedNode;
128132
}
129133

134+
void RNGestureHandlerDetectorShadowNode::updateOrderIndexFromChildren() {
135+
const auto &children = getChildren();
136+
if (children.size() != 1) {
137+
ShadowNode::orderIndex_ = 0;
138+
return;
139+
}
140+
141+
// The detector behaves like a transparent wrapper around its child.
142+
// With a single child, mirror the child's RN-computed order index so styles
143+
// such as zIndex keep affecting sibling ordering despite the extra native
144+
// detector node. With multiple children, no single order index can preserve
145+
// each child's independent ordering relative to outside siblings.
146+
ShadowNode::orderIndex_ = children.front()->getOrderIndex();
147+
}
148+
130149
} // namespace facebook::react

packages/react-native-gesture-handler/shared/shadowNodes/react/renderer/components/rngesturehandler_codegen/RNGestureHandlerDetectorShadowNode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class RNGestureHandlerDetectorShadowNode final
6565
std::shared_ptr<const ShadowNode> unflattenNode(
6666
const std::shared_ptr<const ShadowNode> &node);
6767
void initialize();
68+
void updateOrderIndexFromChildren();
6869

6970
std::optional<LayoutMetrics> previousLayoutMetrics_;
7071
};

0 commit comments

Comments
 (0)