Sibyl
Sibyl

Reputation: 145

react native FlatList re-renders when elements have been added to the array state

When I want to change the array state all of the elements in the FlatList gets re-rendered. I have checked other questions with the same problem but nope I wasn't able to solve it. First, the issue was in my main project but because I wasn't able to solve it I created a clear project with the example I gave below but still, the issue persists. On the main project, KeyExtractor was returning a unique id.

import React, { useEffect, useState, memo } from 'react';
import { FlatList, StyleSheet, Text, View } from 'react-native';

export default function App() {
  const [data, setData] = useState([...Array(5).keys()])

  useEffect(() => {
    setInterval(() => {
      console.log("----------")
      setData(oldArray => [...oldArray, Math.ceil(Math.random() * 5000)])
    }, 2000)
  }, [])

  const RenderItem = memo(({ item }: { item: number }) => {
    return (
      <View>
        { console.log("render", item) }
        <Text>{ item }</Text>
      </View>
    )
  })

  const renderItemHandler = ({ item }: { item: number }) => {
    return <RenderItem item={item} />
  }

  const keyExtractor = (item: number) => item.toString();
  return (
    <View style={styles.container}>
      <FlatList
        style={{ width: 100, backgroundColor: "#7132a8" }}
        data={data}
        renderItem={renderItemHandler}
        keyExtractor={keyExtractor}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

https://snack.expo.dev/@sibyl/flatlist-issue

The screenshot from the React DevTools Re render example

UPDATE

Updated code to use memo

UPDATE Solved it by moving components that use memo to outside of app function

const RenderItem = memo((props: { item: number }) => {
  return (
    <View key={props.item}>
      { console.log("render", props.item) }
      <Text>{ props.item }</Text>
    </View>
  )
})

const renderItemHandler = ({ item }: { item: number }) => {
  return <RenderItem item={item} />
}

export default function App() {....

Upvotes: 0

Views: 2382

Answers (1)

Dobrin Tinchev
Dobrin Tinchev

Reputation: 381

A render call will always try to re-render the children of a component.

You can utilize React.memo https://reactjs.org/docs/react-api.html#reactmemo to prevent the re-render of the child component if you are using functional components

Or shouldComponentUpdate for the old school class components https://reactjs.org/docs/react-component.html#shouldcomponentupdate

Upvotes: 1

Related Questions