I've been having lots of trouble trying to avoid getting the "VirtualizedList: You have a large list that is slow to update" warning when using a <FlatList>
component with React-Native.
I've already done loads of research and Google-Fu to try a solution, but none of the solutions helped, not even the solution on this GitHub issue.
Things to keep in mind:
- I'm using
shouldComponentUpdate() { return false; }
in my List Item component, so they are not updating at all. - The component that renders the FlatList is already a
PureComponent
- I added console.logs in the render methods of my components and can confirm they don't re-render.
- I'm not using anonymous functions, so the
renderItem
component is not being re-initialized on each call.
Important: The warning only seems to occur after switching to a separate tab using my BottomTabNavigator
, but this is confusing because when I do this, the FlatList screen component is not re-rendering and neither are the list items. Since the components aren't re-rendering when browsing to another tab, why would this error happen?
Here's my exact code:
App.tsx
const AppRoutes = [ { name: "Home", Component: HomeScreen }, { name: "Catalog", Component: CatalogScreen }, { name: "Cart", Component: CartScreen }];export const StoreApp = () => { return (<NavigationContainer><StatusBar barStyle="dark-content" /><Tabs.Navigator> {AppRoutes.map((route, index) => <Tabs.Screen key={index} name={route.name} component={route.Component} options={{ headerShown: (route.name !== "Home") ?? false, tabBarIcon: props => <TabIcon icon={route.name} {...props} /> }} /> )}</Tabs.Navigator></NavigationContainer> );};
CatalogScreen.tsx
import React from "react";import { FlatList, SafeAreaView, Text, View, StyleSheet } from "react-native";import { LoadingSpinnerOverlay } from "../components/LoadingSpinnerOverlay";import { getAllProducts, ProductListData } from "../api/catalog";class ProductItem extends React.Component<{ item: ProductListData }> { shouldComponentUpdate() { return false; } render() { return (<View> {console.log(`Rendered ${this.props.item.name}-${Math.random()}`)}<Text style={{height: 100}}>{this.props.item.name}</Text></View> ); }}export class CatalogScreen extends React.PureComponent { state = { productData: [] }; componentDidMount() { getAllProducts() .then(response => { this.setState({ productData: response.data }); }) .catch(err => { console.log(err); }); } private renderItem = (props: any) => <ProductItem {...props} />; private keyExtractor = (product: any) => `${product.id}`; render() { const { productData } = this.state; console.log("CATALOG RENDERED"); return (<SafeAreaView style={styles.pageView}> {!productData.length && <LoadingSpinnerOverlay text="Loading products..." />}<View style={{backgroundColor: "red", height: "50%"}}><FlatList data={productData} removeClippedSubviews keyExtractor={this.keyExtractor} renderItem={this.renderItem} /></View></SafeAreaView> ); }};const styles = StyleSheet.create({ pageView: { height: "100%", position: "relative", }});
Since my components and lists are optimized and I'm still receiving the error, I'm starting to believe that this may be an actual issue with React Native - but if anyone can see what I'm doing wrong, or any workarounds, this would help greatly!