2022-05-29

is this a result of firestore latency or normal behavior

I have a form I am using to allow users to add comments to my site. The form has an input field, a textarea field, and a button. When the button is clicked it runs my addComment() function which adds the name, comment, and timestamp to my firestore collection as a new doc.

It seems like after I click the button to add a comment I have to wait a few seconds before I can post another one. If I try to add a new comment too quickly then request doesn't get sent to my firestore collection, but if I wait a few seconds everything works as expected.

I am curious if this is normal behavior? How can I set it up so users can always post comments without having to wait a few seconds? Can someone explain to me what is happening?

Thanks Update: I have been doing some debugging, and I have noticed that both of the functions getVisitorCount() and getUserComments() from the first useEffect run every time I type something into the name or comment input boxes. I have attached screenshots to showcase what is happening.

On the first initial load of the app: enter image description here

After typing something in the name input box: enter image description here

Finally, typing something into the comment box as well: enter image description here

This is not the desired behavior I want these two functions should not be running when I am typing something into either text field. The getUserComments function should only run on the initial render of the app, and whenever the add comment button is clicked. Could this be what is causing the problems I am experiencing?

import React, { useState, useEffect } from "react";
import { NavBar, Footer, Home, About } from "./imports";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import { db } from "./firebase-config";
import {
  collection,
  getDocs,
  doc,
  updateDoc,
  addDoc,
  Timestamp,
} from "firebase/firestore";

export default function App() {
  const [formData, setFormdata] = useState([]);
  const [numberOfVisitors, setnumberOfVistors] = useState([]);
  const [userComments, setUserComments] = useState([]);

  const portfolioStatsRef = collection(db, "portfolio-stats");
  const userCommentsRef = collection(db, "user-comments");

  const currentNumberOfVisitors = numberOfVisitors.map((visitors) => {
    return (
      <h2 className="p-3 mb-0 bg-dark bg-gradient text-white" key={visitors.id}>
        Number of vistors: {visitors.visitor_count}
      </h2>
    );
  });

  const listOfUserComments = userComments.map((comment) => {
    return (
      <li className="list-group-item" key={comment.id}>
        <div className="d-flex w-100 justify-content-center">
          <h5 className="mb-1">{comment.name}</h5>
          <small>{comment.date.toDate().toString()}</small>
        </div>
        <p className="d-flex justify-content-center mb-1">{comment.comment}</p>
      </li>
    );
  });

  useEffect(() => {
    const getVisitorCount = async () => {
      const dataFromPortfolioStatsCollection = await getDocs(portfolioStatsRef);

      setnumberOfVistors(
        dataFromPortfolioStatsCollection.docs.map((doc) => {
          return { ...doc.data(), id: doc.id };
        })
      );
    };

    const getUserComments = async () => {
      const dataFromUserCommentsCollection = await getDocs(userCommentsRef);

      setUserComments(
        dataFromUserCommentsCollection.docs.map((doc) => {
          return { ...doc.data(), id: doc.id };
        })
      );
    };
    getVisitorCount();
    getUserComments();
  }, [numberOfVisitors, portfolioStatsRef, userCommentsRef]);

  useEffect(() => {
    const updateVisitorCount = async () => {
      const portfolioStatsDoc = doc(
        db,
        "portfolio-stats",
        numberOfVisitors[0].id
      );
      const updatedFields = {
        visitor_count: numberOfVisitors[0].visitor_count + 1,
      };
      await updateDoc(portfolioStatsDoc, updatedFields);
    };

    if (!numberOfVisitors.length) return;

    let sessionKey = sessionStorage.getItem("sessionKey");

    if (sessionKey === null) {
      sessionStorage.setItem("sessionKey", "randomString");
      updateVisitorCount();
    }
  }, [numberOfVisitors]);

  const handleFormData = (event) => {
    setFormdata((prevFormData) => {
      return {
        ...prevFormData,
        [event.target.name]: event.target.value,
      };
    });
  };

  const addComment = async () => {
    const newComment = {
      name: formData.name,
      comment: formData.comment,
      date: Timestamp.now(),
    };
    await addDoc(userCommentsRef, newComment);
  };

  return (
    <>
      <div className="d-flex flex-column overflow-hidden min-vh-100 vh-100">
        <NavBar />
        <div className="row">
          <div className="col text-center">
            {numberOfVisitors.length === 0 && (
              <h2 className="p-3 mb-0 bg-dark bg-gradient text-danger">
                Sorry, the Firestore free tier quota has been met for today.
                Please come back tomorrow to see portfilio stats.
              </h2>
            )}
            {currentNumberOfVisitors}
          </div>
        </div>
        <div className="bg-image">
          <div className="postion-relative">
            <main className="flex-grow-1">
              <div className="container-fluid p-0">
                <Router>
                  <Routes>
                    <Route path="/" element={<Home />} />
                    <Route path="/about" element={<About />} />
                  </Routes>
                  <div className="row">
                    <div className="center-items col">
                      <h4 className="">Comments</h4>
                    </div>
                  </div>
                  <div className="row">
                    <div className="center-items col">
                      <div className="comments-container">
                        {userComments.length === 0 && (
                          <h4 className="text-danger bg-dark m-1 p-1">
                            Sorry, the Firestore free tier quota has been met
                            for today. Please come back tomorrow to see
                            portfilio comments.
                          </h4>
                        )}
                        {listOfUserComments}
                      </div>
                    </div>
                  </div>
                  <div className="row">
                    <div className="center-items col">
                      <h4 className="text-dark">Leave a comment</h4>
                    </div>
                  </div>
                  <div className="row">
                    <div className="center-items col">
                      <form className="comment-form">
                        <div className="form-floating mb-3">
                          <input
                            type="text"
                            className="bg-transparent form-control"
                            id="floatingInput"
                            name="name"
                            onChange={handleFormData}
                          />
                          <label htmlFor="floatingInput">Name</label>
                        </div>
                        <div className="form-floating">
                          <textarea
                            className="form-textarea-field bg-transparent form-control mb-1"
                            name="comment"
                            id="floatingTextarea"
                            onChange={handleFormData}
                          />
                          <label htmlFor="floatingTextarea">Comment</label>
                        </div>
                        <div className="d-grid">
                          <button
                            className="btn btn-primary mb-4"
                            onClick={() => addComment()}
                          >
                            Add Comment
                          </button>
                        </div>
                      </form>
                    </div>
                  </div>
                </Router>
              </div>
            </main>
          </div>
        </div>
        <Footer />
      </div>
    </>
  );
}


No comments:

Post a Comment