Search code examples
react-nativereact-native-flatlist

The performance issue with FlatList in React Native


I have a TabNavigator with two screens, each representing a stack navigator. On the first screen, all recipes are displayed in a FlatList, and I fetch the data from the Redux store. The second screen also contains a FlatList, with data dependent on the first screen and fetched from the store. I modify the state of each individual item in the FlatList on the first screen. There are no issues upon the initial app load, but after navigating to the second screen and returning, the process of adding and removing items from favorites starts to lag. Moreover, the more items are added, the more the function slows down. Here is the link to the repository: https://github.com/AlexeyKaluzhniy/recipesApp

I attempted to use React.memo and FlashList instead of FlatList. While FlashList does improve performance, there are still noticeable delays. It feels like more items are being added than there actually are, and the list constantly re-renders the component. I don't know what the issue is; I really need help.


Solution

  • When you open the Favorites tab and then navigate back to the Recipes tab, the Favorites tab remains mounted. See Navigation lifecycle docs.

    So when you press on a heart button, the Favorites tab re-renders in the background because it is subscribed to the part of the store that is changing.

    You will need to control the Favorites tab based on its focused or blurred state.

    #1. Render nothing when the tab is blurred

    export default function Favorite({ navigation }: FavoriteProps) {
        const favoritesData = useSelector(selectFavoriteData);
        const dispatch = useDispatch();
        const isFocused = useIsFocused();
    
        if (!isFocused) return null;
    
        // return ...
    }
    

    This is the easiest way but the scroll state will be lost when switching between tabs.

    #2. Manually manage store subscription

    export default function Favorite({ navigation }: FavoriteProps) {
        const store = useStore<RootState>();
        const [favoriteIds, setFavoriteIds] = useState<string[]>();
        const favoritesData = store.getState().data.recipes
            .filter(recipe => favoriteIds.includes(recipe.id));
    
        useFocusEffect(useCallback(() => {
            const storeListener = () => setFavoriteIds(store.getState().favorite.recipeIds);
            storeListener();
            return store.subscribe(storeListener);
        }, [store]));
    
        // return ...
    }