xiaolingxiao
xiaolingxiao

Reputation: 4895

react-native flatlist images flicker when list state updating

I have populated a FlatList with data fetched from Google's firebase backend. The implementation is rather standard, here's a stripped down version:

export default class Day extends Component {

state = { data : [], today: false }


componentWillMount = async () => {

    const { today } = this.state;
    const { calendarDb } = this.props

    await calendarDb.onNewAgenda({ 
          day : today
        , then: this.parseOnListed 
    })
}

parseOnListed = blob => {

    const { data } = this.state;
    data.push(blob)
    this.setState({ data: data })
}


renderItem = ({ item }) => 
    <Hour data = {item}/>


render = () => 
    <FlatList  
        data         = {this.state.data}
        renderItem   = {this.renderItem}
        keyExtractor = {item => item.ID}
    />

}

The issue is that every time a new blob is pushed into data, the <Image/> component in <Hour data={item}/> flickers. This makes the list a no-go in terms of user experience. What gives? <Hour/> is standard as well, and more or less look like this:

const Hour = ({ data }) => 
   <View>
       <Image source={{uri:data.uri}}/>
       <Text> {data.name} </Text>
   </View>

The content of <Text> does not flicker, only the image from <Image .../>

Upvotes: 6

Views: 11471

Answers (3)

energy2080
energy2080

Reputation: 46

  1. Check whether keyExtractor is getting unique ID.
  2. Use useCallback
<FlatList
    data={data}
    keyExtractor={(item) => item.id}
    renderItem={({ item, index }) => (
        <ListItem
        data={item}
        index={index}
        key={index + 1}
        />
    )}
/>
    
const ListItem = useCallback(({ data, index, }) => {
   return ( 
     <View key={item.id}>
     ...
     </View>
   );
}, []);

Upvotes: 1

camello222
camello222

Reputation: 94

I found another reason that triggers this issue, of the FlatList flikering on React native. In my case, it happened every time I updated/changed the state of any function component. So, for instance, I was keeping the fetch results (data) and the next-page-id (for the next paginated fetch) in two separate function components:

const [data, setData] = useState([]);
const [pageId, setPageId] = useState(null);

Hence, every time would capture the results of my fetch, I would first set the data update and then the page id. It was the page id update what was causing the flicker.

const onEndReachedFetch = async () ={
    fetch(pageId).then(result => {
        setData(result.Data);
        setPageId(result.pageId);
    });
}

The fix was just to put the state data together so there is a single update instead. Then react is happy and doesn't flicker when adding new items to the list.

const onEndReachedFetch = async () ={
    fetch(pageId).then(result => {
        setResult(result);
    });
}

Beware of any side states that you may be updating in the background, as they may also cause the flickering if they are triggered by anything on the FlatList.

Upvotes: 2

Rushabh Singh
Rushabh Singh

Reputation: 121

Check whether keyExtractor is getting unique ID or not. The flat list is re-rendering on state update and images are downloaded again. Because, each row is not uniquely identified as said in comments by @Guruparan Giritharan.

Upvotes: 12

Related Questions