【问题标题】:All comment forms submit the same docId所有评论表单提交相同的 docId
【发布时间】:2021-10-23 14:10:53
【问题描述】:

我有一个 react 应用程序(一种 twitter 克隆),它使用 firestore 来存储帖子和帖子上的 cmets。使用 array.map() 将每个帖子呈现为数组中的一个元素。每个帖子都有一个评论按钮,可以打开一个表单来接受评论并将其添加到帖子中。当我输入评论并提交时,无论哪个帖子包含被点击的评论按钮,最上面的帖子总是评论的(最近保存的firestore文档的docId总是由评论按钮而不是对应的docId提交到该组件的实例)。

帖子地图(称为“嚎叫”):

<div className="timeline">
  {sortedHowls &&
    sortedHowls.map((howl) => (
      <Howl
        key={howl.id}
        image={howl.image}
        text={howl.text}
        time={howl.time}
        userId={howl.userId}
        docId={howl.id}
        comments={howl.comments}
        likes={howl.likes}
      />
    ))}
</div>

嚎叫组件如下所示:

    import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { useFirestoreConnect } from "react-redux-firebase";
import { firestore } from "../../../firebase-store";
// styles
import "./Howl.scss";
// components
import Avatar from "../Avatar/Avatar";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
// functions
import timeCalc from "./timeCalc";
// icons
import { faStar, faComment } from "@fortawesome/free-solid-svg-icons";

const Howl = ({ docId, userId, text, image, time, comments, likes }) => {
  useFirestoreConnect([{ collection: "users" }]);

  const [commenting, toggleCommenting] = useState(false);
  const [newComment, setNewComment] = useState("");
  const [users, setUsers] = useState(null);
  const [user, setUser] = useState(null);

  const getUsers = useSelector((state) => state.firestore.ordered.users);

  useEffect(() => {
    if (!users) {
      setUsers(getUsers);
    } else {
      setUser(users.find((doc) => doc.uid === userId));
    }
  }, [users, user, userId, getUsers]);

  const handleLike = () => {
    const newLikesTotal = likes + 1;
    firestore.collection("howls").doc(docId).update({ likes: newLikesTotal });
  };

  const handleComment = () => {
    toggleCommenting(!commenting);
  };

  const handleChange = (event) => {
    setNewComment(event.currentTarget.value);
  };

  const submitComment = (event) => {
    event.preventDefault();
    const { id } = event.currentTarget;
    console.log(event.currentTarget);

    const resetComment = () => {
      toggleCommenting(!commenting);
      setNewComment("");
    };

    if (comments) {
      firestore
        .collection("howls")
        .doc(id)
        .update({
          comments: [...comments, newComment],
        })
        .then(() => resetComment());
    } else {
      firestore
        .collection("howls")
        .doc(id)
        .update({ comments: [newComment] })
        .then(() => resetComment());
    }
  };

  return (
    <div className="howl">
      <div className="avatar-container">
        <Avatar
          photoURL={user ? user.photoURL : ""}
          displayName={user ? user.displayName : ""}
        />
      </div>
      <div className="name-text-img-container">
        <p className="userName">
          {user && user.displayName} - {timeCalc(Date.now(), time)}
        </p>
        <p className="howl-text">{text}</p>
        <div className="img-container">
          {image ? (
            <img src={image} alt="user uploaded" className="img" />
          ) : null}
        </div>
        <div className="buttons-container">
          <form action="" className="buttons">
            <label htmlFor="comment-button">
              <FontAwesomeIcon icon={faComment} className="image-icon" />
            </label>
            <input
              id="comment-button"
              type="checkbox"
              onClick={handleComment}
              style={{ display: "none" }}
            />
            <label htmlFor="like-button">
              <FontAwesomeIcon icon={faStar} className="image-icon" />
            </label>
            <input
              id="like-button"
              type="checkbox"
              onClick={handleLike}
              style={{ display: "none" }}
            />
            <label htmlFor="like-button">{likes > 0 && likes}</label>
          </form>
        </div>
        {commenting && (
          <div className="comment-form">
            <form action="submit" onSubmit={submitComment} id={docId}>
              <input
                type="text"
                name="comment-input"
                className="comment-input"
                maxLength={128}
                onChange={handleChange}
                value={newComment}
                placeholder="Enter comment"
              />
              <div className="buttons">
                <button type="submit">Submit</button>
                <button onClick={() => toggleCommenting(!commenting)}>
                  Cancel
                </button>
              </div>
            </form>
          </div>
        )}
        <div className="comments">
          {comments
            ? comments.map((comment, index) => {
                return (
                  <p key={index} className="comment">
                    {comment}
                  </p>
                );
              })
            : null}
        </div>
      </div>
    </div>
  );
};

export default Howl;

如何获得评论按钮以指定要更新的正确文档?

链接到我的完整版repo

【问题讨论】:

    标签: javascript reactjs firebase google-cloud-firestore


    【解决方案1】:

    原来问题出在这里:

         <form action="" className="buttons">
            <label htmlFor="comment-button">
              <FontAwesomeIcon icon={faComment} className="image-icon" />
            </label>
            <input
              id="comment-button"
              type="checkbox"
              onClick={handleComment}
              style={{ display: "none" }}
            />
            <label htmlFor="like-button">
              <FontAwesomeIcon icon={faStar} className="image-icon" />
            </label>
            <input
              id="like-button"
              type="checkbox"
              onClick={handleLike}
              style={{ display: "none" }}
            />
            <label htmlFor="like-button">{likes > 0 && likes}</label>
          </form>
    

    通过使用表单和输入作为按钮而不是使用&lt;button /&gt; 元素,它以某种方式混淆了&lt;Howl /&gt; 的哪个实例正在打开评论表单以及因此哪个docId 被发送到submitComment。更正&lt;Howl /&gt; 组件:

    import React, { useEffect, useState } from "react";
    import { useSelector } from "react-redux";
    import { useFirestoreConnect } from "react-redux-firebase";
    import { firestore } from "../../../firebase-store";
    // components
    import Avatar from "../Avatar/Avatar";
    import CommentInput from "./CommentInput";
    import Comment from "./Comment";
    import ViewProfile from "../ViewProfile/ViewProfile";
    import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
    // functions
    import timeCalc from "./timeCalc";
    // styles
    import "./Howl.scss";
    // icons
    import { faStar, faComment } from "@fortawesome/free-solid-svg-icons";
    
    const Howl = ({ howl }) => {
      useFirestoreConnect([{ collection: "users" }]);
    
      const [commenting, toggleCommenting] = useState(false);
      const [newComment, setNewComment] = useState("");
      const [users, setUsers] = useState(null);
      const [op, setOp] = useState(null);
      const [showProfile, setShowProfile] = useState(false);
    
      const { docId, userId, text, likes, comments, time, image } = howl;
    
      const getUsers = useSelector((state) => state.firestore.ordered.users);
    
      const currentUser = useSelector((state) => state.firebase.auth);
    
      // establish user that posted this howl (op = original poster)
      useEffect(() => {
        users ? setOp(users.find((doc) => doc.uid === userId)) : setUsers(getUsers);
      }, [users, op, userId, getUsers]);
    
      const handleLike = () => {
        const index = likes.indexOf(currentUser.uid);
        let newLikes = [...likes];
    
        if (index > 0) {
          newLikes.splice(index, 1);
        } else if (index === 0) {
          if (likes.length > 1) {
            newLikes.splice(index, 1);
          } else {
            newLikes = [];
          }
        } else {
          newLikes = [...newLikes, currentUser.uid];
        }
    
        firestore.collection("howls").doc(docId).update({ likes: newLikes });
      };
    
      const handleChange = (event) => {
        setNewComment(event.currentTarget.value);
      };
    
      const submitComment = (event) => {
        event.preventDefault();
    
        const { id } = event.currentTarget;
        const { uid, photoURL } = currentUser;
    
        const resetComment = () => {
          toggleCommenting(!commenting);
          setNewComment("");
        };
    
        firestore
          .collection("howls")
          .doc(id)
          .update({
            comments: [
              ...comments,
              { uid: uid, photoURL: photoURL, text: newComment },
            ],
          })
          .then(() => resetComment());
      };
    
      return (
        <div className="howl">
          <div className="avatar-container">
            <button className="show-profile" onClick={() => setShowProfile(true)}>
              <Avatar
                photoURL={op ? op.photoURL : ""}
                displayName={op ? op.displayName : ""}
              />
            </button>
          </div>
          <div className="name-text-img-container">
            <p className="userName">
              {op && op.displayName} - {timeCalc(Date.now(), time)}
            </p>
            <p className="howl-text">{text}</p>
            <div className="img-container">
              {image && <img src={image} alt="user uploaded" className="img" />}
            </div>
            <div className="buttons-container">
              <div className="buttons">
                <button className="comment-button">
                  <FontAwesomeIcon
                    icon={faComment}
                    className="image-icon"
                    onClick={() => toggleCommenting(!commenting)}
                  />
                </button>
                <button className="like-button" onClick={handleLike}>
                  <FontAwesomeIcon
                    icon={faStar}
                    className={
                      currentUser && likes.includes(currentUser.uid)
                        ? "image-icon liked"
                        : "image-icon"
                    }
                  />
                </button>
                <p>{likes.length > 0 && likes.length}</p>
              </div>
            </div>
            {commenting && (
              <CommentInput
                submitComment={submitComment}
                docId={docId}
                toggleCommenting={toggleCommenting}
                commenting={commenting}
                handleChange={handleChange}
                newComment={newComment}
              />
            )}
            {showProfile && (
              <ViewProfile
                user={op}
                close={() => setShowProfile(false)}
                update={false}
              />
            )}
            <div className="comments">
              {comments &&
                comments.map((comment, index) => {
                  return <Comment key={`comment${index}`} comment={comment} />;
                })}
            </div>
          </div>
        </div>
      );
    };
    
    export default Howl;
    

    【讨论】:

      猜你喜欢
      • 2021-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-24
      • 2019-08-01
      • 2017-11-14
      • 1970-01-01
      相关资源
      最近更新 更多