yashatreya
yashatreya

Reputation: 842

previous state persisting even after calling setState() with new data

I am making a task app using Firebase Cloud Firestore

I have added a realtime listener for re-rendering the Flatlist with new tasks if any are added.

But I am facing an issue such that the state tasks = [] is getting appended to the old state which results in duplication of Tasks in Flatlist.

I wish to just refresh the whole list.

This is my code for the realtime listener:


this.state = {
      tasks: [],
    };

fetchTasks() {
    try {
      this.setState({loading: true});
      const uid = auth().currentUser.uid;
      const tempTasks = [];
      firestore()
        .collection('Tasks')
        .where('uid', '==', `${uid}`)
        .onSnapshot(snapshot => {
          snapshot.forEach(doc => {
            console.log('realtime: ', JSON.stringify(doc.data(), null, 2));
            tempTasks.push({
              taskId: doc.id,
              data: doc.data(),
            });
          });
          this.setState({tasks: []});
          this.setState({tasks: tempTasks, loading: false});
          console.log('tasks: ', this.state.tasks.length);
        });
    } catch (e) {
      this.setState({loading: false});
      Alert.alert('Error fetching tasks', `${e}`, [{text: 'OK'}]);
      console.log('err in realtime', e);
    }
  }

render() {
   return (
      <FlatList
        data={this.state.tasks}
        renderItem={this._renderItem}
        keyExtractor={(item, index) => index.toString()}
      />
    )

Initially: One task enter image description here

Final: After adding a task, duplicate of Task 1 also appear as the tasks = [] is appended in the state instead of refreshing with both task 1 and task 2.

enter image description here

Log of tempTasks:

tempTasks [
  {
    "taskId": "FljhGGlsFN7yrD4GajDe",
    "data": {
      "status": "pending",
      "createdOn": {
        "_seconds": 1578761968,
        "_nanoseconds": 66000000
      },
      "title": "Task 1",
      "deadline": {
        "_seconds": 1578761940,
        "_nanoseconds": 0
      },
      "description": "apsdfplsdv",
      "author": "yashGmail",
      "uid": "t2kHrhIMbLggj2BpxKbJrPW9GL42"
    }
  },
  {
    "taskId": "GhF5nYalbTZZZH5j2lNO",
    "data": {
      "status": "pending",
      "createdOn": {
        "_seconds": 1578762188,
        "_nanoseconds": 226000000
      },
      "title": "Task 2",
      "deadline": {
        "_seconds": 1578761940,
        "_nanoseconds": 0
      },
      "description": "asdvlksdk",
      "author": "yashGmail",
      "uid": "t2kHrhIMbLggj2BpxKbJrPW9GL42"
    }
  }
]

Help would be very much appreciated.

Upvotes: 0

Views: 254

Answers (1)

Ashish
Ashish

Reputation: 4330

You need to check if event .onSnapshot(snapshot => {}) is triggered with only the newer elements or it gets triggered with all the elements. From your code it is clear that you are updating state.tasks with tempTasks so it is very much clear that data inside tempTasks is also duplicate, the reason for which I have explained above.

You can try this if onSnapshot is triggered with all the data:

firestore()
.collection('Tasks')
.where('uid', '==', `${uid}`)
.onSnapshot(snapshot => {
  console.log(snapshot) // This to check what data is inside snapshot
  const tempTasks = snapshot.map(doc => ({
    taskId: doc.id,
    data: doc.data(),
  }))
  this.setState({tasks: tempTasks, loading: false});
})

Upvotes: 2

Related Questions