0

I am using React Native and Firebase Realtime Database. I am experiencing two problems with the FlatList component:

  1. I am getting a lot of "duplicate key" errors whenever the list re-renders. I am not sure why I am getting this problem because I am setting the key of every item in my list as the snap.key value generated by Firebase, which is unique (and I have verified this in my logs).

  2. The list sometimes does not re-render, even when I scroll up or down on it. This "sometimes" behavior is throwing me off, and I have not been able to debug it. I am using the ".on" method for getting my list from the Firebase Realtime Database.

This is the code that I am using:

export default class FlatListPage extends React.PureComponent {

    constructor(props) {
        super(props); 
        this.state = { 
            data: [],
        }; 
    }

    makeRemoteRequest = () => {
        var items = []; 
        DB.on('value', (snap) => {
            this.getItems(snap, items); 
            items = items.reverse(); 
            this.setState(
                {data: items}
            ); 
            console.log(this.state.data);  //checking key properties are unique 
        }); 

    }

    getItems = (snap, items) => {
        snap.forEach((child) => {
            items.push({
                key: child.key, 
                status: child.val().status, 
                location: child.val().location, 
            });
        });
    }

    componentWillMount(){
        this.makeRemoteRequest(); 
    }

    render() {
        return (
            <View>
                <FlatList
                    data={this.state.data}
                    renderItem={({item}) => <MyListItem item={item} />}
                />
            </View>
        );
    }
}
user8951490
  • 833
  • 1
  • 10
  • 21

2 Answers2

1

You're receiving duplicate keys because you're not resetting the items array when receiving a new value event from firebase. This means you're simply re-adding the same items over and over again.

Update your makeRemoteRequest method to recreate the array each time you get a value event as follows:

makeRemoteRequest = () => {
    DB.on('value', (snap) => {
        var items = [];
        this.getItems(snap, items); 
        items = items.reverse(); 
        this.setState(
            {data: items}
        ); 
        console.log(this.state.data);  //checking key properties are unique 
    }); 
}

I'm not sure about number 2 - it might be that the above fixes it as a side effect.

Chris
  • 217
  • 1
  • 2
  • 10
  • Thank you! Good catch, it is functioning much smoother now and #2 was taking care of as a side effect. If I wanted to clear the `var items' variable outside of the .on function, should I do so inside the lifecycle method componentWillUpdate()? I may have to add more data to it (using several .on connections), so I won't be able to place it inside any one of them. – user8951490 Jan 26 '18 at 12:26
0

instead of getting the whole list every time I suggest to get all elements .once and then use 'child_added' event and .limitToLast(1) to get only new items and add them to your array. Also, I noticed that you are pushing items to the array and then reversing it. You can use .unshift method that inserts items at the beginning of the array so you do not have to reverse it later.

yernarun
  • 326
  • 2
  • 10