Home > Mobile >  Firebase reading data two times from firestore
Firebase reading data two times from firestore

Time:08-31

I am trying to read the data from a Firebase Firestore collection called 'posts'. Its having few documents in it. When I am using the following code to read data, I am able to read it but two times:

  • code in posts.jsx file:
import React, { useEffect, useState } from "react";
import '../index.css';
import '../../node_modules/antd/dist/antd.min.css';
import PostSnippet from './PostSnippet';
import _ from 'lodash';
import { PageHeader } from "antd";
import { db } from '../firebase.js';
import { collection, getDocs } from "firebase/firestore";


function Posts(props) {

  const [posts, setPosts] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      const postRef = collection(db, 'posts');
      const postSnap = await getDocs(postRef);
      postSnap.forEach(doc => {
        let data = doc.data()
        let { id } = doc

        let payload = {
          id,
          ...data,
        }
        setPosts((posts) => [...posts, payload])
      })
    }

    fetchData()
      .catch(console.error);

  }, [])

  return (
    <div className="posts_container">
      <div className="page_header_container">
        <PageHeader
          style={{
            border: '5px solid rgb(235, 237, 240)',
            fontSize: '25px',
            margin: '40px',
          }}
          title="Post"
        />
      </div>

      <div className="articles_container">
        {
          _.map(posts, (article, idx) => {
            return (
              <PostSnippet
                key={idx}
                id={article.id}
                title={article.title}
                content={article.content.substring(1, 300)} />
            )
          })
        }

      </div>
    </div>
  )
}


export default Posts;
  • Code in PostSnippet.jsx file which is used to give the view to individual cards:
import React from "react";
import { Card } from "antd";
import { Link } from "react-router-dom";

const PostSnippet = (props) => {
  return (
    <>
      <div className="post_snippet_container" style={{ margin: "40px" }}>
        <Card
          type="inner"
          title={props.title}
          extra={
            <Link to={`/post/${props.id}`}>
              Refer the Article
            </Link>}
        >
          <p className="article_content">
            {
              props.content.split('\n').map((paragraph, idx) => {
                return <p key={idx}>{paragraph}</p>
              })
            }
          </p>
        </Card>
      </div>
    </>

  )
}


export default PostSnippet;
  • Actual data in Firestore: enter image description here

  • Retried data from the firestore: enter image description here

CodePudding user response:

setPosts((posts) => [...posts, payload])

You only ever add to the array, so when data is fetched for the second time, you grow your array to twice the size. Instead, replace the array with the new data. That way the second fetch will overwrite the first:

const fetchData = async () => {
  const postRef = collection(db, 'posts');
  const postSnap = await getDocs(postRef);
  const newPosts = postSnap.docs.map(doc => {
    return {
      id: doc.id,
      ...doc.data(),
    }
  });
  setPosts(newPosts);
}
  • Related