Skip to content

Instantly share code, notes, and snippets.

@Ali72
Created September 20, 2024 13:03
Show Gist options
  • Save Ali72/0a126513a7194d42739135f5a1468aff to your computer and use it in GitHub Desktop.
Save Ali72/0a126513a7194d42739135f5a1468aff to your computer and use it in GitHub Desktop.
HorizontalRTLSupportFlatList
import React, {useEffect, useRef, useState} from 'react';
import {FlatList, I18nManager} from 'react-native';
/**
* HorizontalRTLSupportFlatList
*
* This component is a custom wrapper around React Native's FlatList to add support
* for Right-to-Left (RTL) layouts when rendering horizontal lists. It automatically
* handles reversing the scroll direction and item order in RTL mode while maintaining
* the correct visual order of list items. Additionally, it includes logic to manage
* scrolling behavior in large screens and to handle potential scroll failures.
*
* Why this component was created:
* - React Native's FlatList does not provide native RTL scrolling for horizontal lists.
* - This component ensures correct scrolling direction and item order in RTL layouts.
* - It solves the need for a reusable RTL-friendly horizontal FlatList component.
*
* Key Features:
* - Automatically flips the FlatList's horizontal scrolling in RTL mode by reversing the data and using the `inverted` prop.
* - Reverses the data array to display items in the correct visual order for RTL layouts.
* - Scrolls to the last item in RTL mode (or the first item in LTR mode) after the layout is complete.
* - Adjusts the scroll offset to center the selected item for large screens.
* - Handles potential `scrollToIndex` failures by using `onScrollToIndexFailed` to retry scrolling after a small delay.
*
* Scroll Behavior:
* - Uses the `inverted` prop to flip the scrolling direction in RTL mode without the need for a `scaleX` transformation.
* - Scrolls to the last item in RTL mode once the layout is complete and retries scrolling on failure.
* - Adjusts the scroll offset on large screens for better centering of items.
*/
const HorizontalRTLSupportFlatList = ({renderItem, data, ...props}) => {
const flatListRef = useRef(null); // Reference for accessing FlatList methods like scrollToIndex
const [isLayoutComplete, setIsLayoutComplete] = useState(false); // Tracks whether the FlatList has completed layout
const [isScrollToIndexFailed, setScrollToIndexFailed] = useState(false); // Tracks if scrollToIndex has failed
// Reverse the data if RTL mode is active to ensure the correct visual order of items.
const processedData = I18nManager.isRTL ? [...data].reverse() : data;
useEffect(() => {
// Scroll to the last item in RTL mode after the layout is complete
if (I18nManager.isRTL && isLayoutComplete && flatListRef.current && processedData.length > 0) {
flatListRef.current.scrollToIndex({index: processedData.length - 1, animated: false});
}
}, [isLayoutComplete, isScrollToIndexFailed, processedData]);
return (
<FlatList
ref={flatListRef} // Ref to programmatically control FlatList
horizontal // Specifies horizontal list layout
inverted={I18nManager.isRTL} // Inverts scrolling in RTL mode
data={processedData} // Use processed (reversed) data for correct RTL order
{...props} // Spread other props like keyExtractor, extraData, etc.
renderItem={renderItem} // Function to render each item in the list
onLayout={() => setIsLayoutComplete(true)} // Trigger layout completion callback
onScrollToIndexFailed={info => {
// Handle scrollToIndex failure and retry after a short delay
const wait = new Promise(resolve => setTimeout(resolve, 200));
wait.then(() => {
setScrollToIndexFailed(true);
});
}}
/>
);
};
export default HorizontalRTLSupportFlatList;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment