Search code examples
reactjsgoogle-cloud-firestoreredux-toolkitrtk-query

How to perform optimistic updates with rtk query?


I am trying to do optimistic updates with rtk query but it is not working. I have a twitter clone where when i like a tweet i want it to do it using optimistic update so that it is instantly reflected on the UI. So what i do is i check if a post is liked and if it is display a red heart otherwise a white heart. But if i click like it is not appearing instanlty. Only when i refresh the page it shows that i have liked it. So that means optimistic updates isn't working. Can anyone tell me how to get it to work??

postSlice.ts likeTweet query

likeTweet:build.mutation({
    async queryFn({id,currUserId}):Promise<any>{
      try{
        let likedDocRef = doc(db,`tweets/${id}`);
        updateDataFirebase(likedDocRef,'likedBy',currUserId)
        
        return {data:'ok'} 
      }
      catch(err){
        return {error:err}
      }
    },
    async onQueryStarted({id,currUserId}, { dispatch, queryFulfilled }) {
      
      const patchResult = dispatch(
        apiSlice.util.updateQueryData<string>('getPosts', undefined, (draft:Posts[]) => {
          console.log(draft)
          
          const post = draft.find(post => post.id === id)
            if (post) {
              post?.likedBy.push(currUserId)
            }
          console.log(post)
        })
      )
      console.log(patchResult)
      try {
        await queryFulfilled
      } catch {
        patchResult.undo()
      }
    }
  })

getPosts

 getPosts: build.query<Posts[],void>({
      async queryFn(currUserId):Promise<any>{
        try{
          let followingsArr=await getFollowingArrFirebase(currUserId);
          let tweetsArr: { }[]=[];
          const q=query(collection(db,'tweets'), where("creatorId", "in" , followingsArr))   
          tweetsArr=await getDataFirebase(q)
          //console.log(tweetsArr)
          return { data:tweetsArr }
        }

        catch(err:any){
          return{error:err} 
        }

    },providesTags: ['Posts']})

Fetching and updating data from firestore util functions

export const getDataFirebase=async (q:any)=>{
  const querySnapshot = await getDocs(q)
  return querySnapshot.docs.map((doc)=> ({id: doc.id, ...doc.data() as object}))
}

export const updateDataFirebase=async (docRef:DocumentReference,property:string,id:string)=>{
  let docData=(await getDoc(docRef)).data();
  let arr=docData?.[property]??[];
  //console.log(arr,docData?.[property]);
  if(arr.includes(id)) arr=arr.filter(itemId=>itemId!=id);
  else arr.push(id);
  await updateDoc(docRef,property,arr);
}

Solution

  • i was using a query key in getPosts() but was not specifying it in the

    apiSlice.util.updateQueryData<string>('getPosts', undefined, (draft:Posts[]) => {}
    

    It should instead be

    apiSlice.util.updateQueryData<string>('getPosts', currUserId, (draft:Posts[]) => {}