reactjs – React button needs to be clicked twice to run the onClick event

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. I am saving both fields in two different state variables using the Onchange prop on the input field, and textarea. When the button is clicked it runs my addComment() function which adds the new name and comment to my firestore database. Everything works correctly the problem is that I have to click the button twice in order for my addComment() function to run. I think it has something to with state, but I am not sure. An explanation and any possible solutions would be appreciated.

Update: I misdiagnosed the problem. I don’t have to click the button twice the click event fires on every single click. The problem is that I was trying to add a new comment too quickly after posting one. 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 the 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? Also I made some changes to the code. The new version of code is updated in the question.

Thanks

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>
    </>
  );
}

Leave a Comment