Skip to content

Commit 9419c74

Browse files
committed
fix(VirtualizedList): sync virtualization logic with local direction style
Summary: This commit fixes the blank rendering issue (Issue #55433) that occurs when a VirtualizedList is used in an RTL environment but explicitly styled as LTR. The root cause was a mismatch between the JS-level coordinate normalization and the Native-level layout direction. While the native ScrollView rendered as LTR, the JS logic still applied RTL mirror calculations based on the global I18nManager state. Changes: 1. Updated `_orientation()` to prioritize the component's `style.direction` over the global `I18nManager.isRTL` setting. 2. In `render()`, explicitly calculated an `orientationStyle` based on the resolved direction and injected it into the ScrollView's style array. 3. This ensures that `_offsetFromScrollEvent` always uses a coordinate system that is perfectly aligned with the actual rendered layout. Fixes: #55433
1 parent df6f8ea commit 9419c74

1 file changed

Lines changed: 22 additions & 9 deletions

File tree

‎packages/virtualized-lists/Lists/VirtualizedList.js‎

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -924,11 +924,13 @@ class VirtualizedList extends StateSafePureComponent<
924924
const {ListEmptyComponent, ListFooterComponent, ListHeaderComponent} =
925925
this.props;
926926
const {data, horizontal} = this.props;
927+
const isRTL = this._orientation().rtl
927928
const inversionStyle = this.props.inverted
928929
? horizontalOrDefault(this.props.horizontal)
929-
? styles.horizontallyInverted
930+
? [styles.horizontallyInverted]
930931
: styles.verticallyInverted
931932
: null;
933+
const orientationStyle = {direction: isRTL ? 'rtl' : 'ltr'}
932934
const cells: Array<any | React.Node> = [];
933935
const stickyIndicesFromProps = new Set(this.props.stickyHeaderIndices);
934936
const stickyHeaderIndices = [];
@@ -1106,8 +1108,8 @@ class VirtualizedList extends StateSafePureComponent<
11061108
: this.props.inverted,
11071109
stickyHeaderIndices,
11081110
style: inversionStyle
1109-
? [inversionStyle, this.props.style]
1110-
: this.props.style,
1111+
? [inversionStyle, this.props.style, orientationStyle]
1112+
: [this.props.style, orientationStyle],
11111113
isInvertedVirtualizedList: this.props.inverted,
11121114
maintainVisibleContentPosition:
11131115
this.props.maintainVisibleContentPosition != null
@@ -1502,7 +1504,7 @@ class VirtualizedList extends StateSafePureComponent<
15021504
}
15031505

15041506
_selectLength(
1505-
metrics: Readonly<{
1507+
metrics: $ReadOnly<{
15061508
height: number,
15071509
width: number,
15081510
...
@@ -1517,13 +1519,24 @@ class VirtualizedList extends StateSafePureComponent<
15171519
return this._orientation().horizontal ? x : y;
15181520
}
15191521

1520-
_orientation(): ListOrientation {
1521-
return {
1522-
horizontal: horizontalOrDefault(this.props.horizontal),
1523-
rtl: I18nManager.isRTL,
1524-
};
1522+
_orientation(): ListOrientation {
1523+
const horizontal = horizontalOrDefault(this.props.horizontal);
1524+
const flatStyle = StyleSheet.flatten(this.props.style);
1525+
const localDirection = flatStyle?.direction;
1526+
1527+
let isRTL = I18nManager.isRTL;
1528+
if (localDirection === 'rtl') {
1529+
isRTL = true;
1530+
} else if (localDirection === 'ltr') {
1531+
isRTL = false;
15251532
}
15261533

1534+
return {
1535+
horizontal,
1536+
rtl: isRTL,
1537+
};
1538+
}
1539+
15271540
_maybeCallOnEdgeReached() {
15281541
const {
15291542
data,

0 commit comments

Comments
 (0)