【问题标题】:Prevent Click Callback From Doubling Doubling React防止点击回调加倍加倍反应
【发布时间】:2021-08-30 22:31:59
【问题描述】:

请帮我弄清楚为什么事件监听器的回调会执行两次:因为我需要离开cmets这样的功能,但是当我点击发布按钮时,回调会立即执行两次。我尝试添加加倍防止器,在 useState 中声明 cllciked var,但它无论如何都没有帮助。即使我单击提交按钮而不是双击,也会发生这种情况。

这是我的组件的代码:

export default function SpecificPostCommentsExtended({ article }) {
  const [prev, setPrev] = useState("");
  const [loaded, setLoaded] = useState(false);
  const [clicked, setClicked] = useState(false);
  const [comments, setComments] = useState([]);
  const [newArticle, setNewArticle] = useState(false);
  async function changePrevState(_id) {
    setPrev(_id);
    console.log(_id, "-is id");
    console.log(await prev, "- prev");
  }
  const ifNoCom = async () => {
    setComments([]);
    setLoaded(true);
    setTimeout(() => {
      document.querySelector("#confirm").addEventListener("click", async () => {
        if(!clicked) {
          setClicked(true);
          alert("comment");
        
        const {data} = await axios({
          url: vars.BACKENDURL + "/comment",
          withCredentials: true,
          method: "POST",
          data: {
            article: article,
            comment: {
              content: document.querySelector("#commentcontent").value,
              prevId: prev === "" ? null : prev,
            },
          },
        });
        if(typeof data != "object") {
        return cogoToast.error("Please sign in first!")
      }
        setLoaded(true);
        setPrev("");
        setClicked(true);
        console.log(data);
        }
        else {
          cogoToast.warn("Already commenting...")
        }
      });
    }, 30);
  };
  const ifCom = async () => {
    setComments([]);
    let i = 0;
    await article.commentsArr.forEach(async (c) => {
      const { data } = await axios({
        url: vars.BACKENDURL + "/getcomment",
        withCredentials: true,
        method: "POST",
        data: { comment: { _id: c } },
      });
      console.log(data);
      if(typeof data != "object") {
        return cogoToast.error("Please sign in first!")
      }
      if (!comments.includes({ ...data })) {
        setComments((current) => [...current, { ...data }]);
      }
      i++;
      if (i >= article.commentsArr.length - 1) {
        setLoaded(true);
        console.log("COMMENTS", comments);
        setTimeout(() => {
          document
            .querySelector("#confirm")
            .addEventListener("click", async () => {
              if(!clicked) {
                setClicked(true);
              console.log("It's prev - ", prev, "!lalalal");
              const data = await axios({
                url: vars.BACKENDURL + "/comment",
                withCredentials: true,
                method: "POST",
                data: {
                  article: article,
                  comment: {
                    content: document.querySelector("#commentcontent").value,
                    prevId: prev === "" ? null : prev,
                  },
                },
              });
              setPrev("");
              setClicked(false);
              }
              else {
          cogoToast.warn("Already commenting...")
        }
              
            });
        }, 30);
      }
    });
  };
  const getComments = async () => {
    setComments([]);
    setLoaded(false);
    if (article.commentsArr.length === 0) {
      ifNoCom();
    } else {
      ifCom();
    }
  };

  useEffect(() => {
    getComments();
  }, [prev]);
  return (
    <>
      <Header>
        <HeaderImg src="../../assets/headerpic.png" />
        <Navbar>
          <span>mypage</span>| <span>log out</span>
        </Navbar>
      </Header>
      <Content>
        <SideBar />
        <RightFrame>
          {loaded === false ? (
            <CircularProgress />
          ) : (
            <>
              <UpperBlock>
                <Title>
                  {article.group.toLowerCase()}
                  <Subtitle>
                    <span>previous</span>
                    <span>next</span>
                    <span>list</span>
                  </Subtitle>
                </Title>

                <PostContainer>
                  <PostDecription>
                    <div className="left">
                      <h2>{article.title}</h2>
                      <span>{article.writer}</span>
                      <span>{article.date}</span>
                    </div>
                    <div className="right">
                      <span
                        onClick={async () => {
                          window.location = `/${article._id}/edit`;
                        }}
                      >
                        edit
                      </span>
                      <span>|</span>
                      <span
                        onClick={async () => {
                          if (
                            !window.confirm(
                              "Are you sure you want to delete this post?"
                            )
                          ) {
                            return;
                          }
                          const { data } = await axios({
                            url: vars.BACKENDURL + `/deletepost`,
                            withCredentials: true,
                            method: "DELETE",
                            data: {
                              post: {
                                id: article._id,
                              },
                            },
                          });
                          alert(data);
                          window.location = "/mzs-general";
                        }}
                      >
                        delete
                      </span>
                    </div>
                  </PostDecription>
                  <PostContents>
                    <h3>Contents</h3>
                    <p>{article.content}</p>
                  </PostContents>
                </PostContainer>
              </UpperBlock>
              <LowerBlock>
                <ReportBtns>
                  <ReportBtnMock>inappropriate language</ReportBtnMock>
                  <ReportBtnMock>misinformation</ReportBtnMock>
                </ReportBtns>
                <LowerRightFrame>
                  <div>
                    <span
                      onClick={() => {
                        window.location = "/specificpost/" + article._id;
                      }}
                    >
                      <img src="../../assets/comments.png" /> Comments{" "}
                      {article.comments}
                    </span>

                    <span
                      onClick={async () => {
                        const { data } = await axios({
                          url: vars.BACKENDURL + "/like",
                          method: "POST",
                          withCredentials: true,
                          data: {
                            post: article,
                          },
                        });
                        cogoToast.success(data);
                      }}
                    >
                      <img src="../../assets/likes.png" /> Likes {article.likes}
                    </span>
                  </div>
                  <div>
                    <span
                      onClick={async () => {
                        const { data } = await axios({
                          url: vars.BACKENDURL + "/like",
                          method: "POST",
                          withCredentials: true,
                          data: {
                            post: article,
                          },
                        });
                        alert(data);
                      }}
                    >
                      Like
                    </span>
                    <span>|</span>
                    <span
                      onClick={async () => {
                        const { data } = await axios({
                          url: vars.BACKENDURL + "/report",
                          method: "POST",
                          withCredentials: true,
                          data: {
                            post: article,
                          },
                        });
                        alert(data);
                      }}
                    >
                      Report
                    </span>
                  </div>
                </LowerRightFrame>
                <CommentsBlock id="commentsblock">
                  {comments.length === 0 ? (
                    <>No comments yet</>
                  ) : (
                    comments.map((c, i) => {
                      return (
                        <>
                          <Comment key={i}>
                            <Nickname>{c.comment.author}</Nickname>
                            <Contents>{c.comment.content}</Contents>
                            <LowerCommentContainer>
                              <span>{c.comment.date}</span>
                              <span
                                onClick={(e) => {
                                  changePrevState(c.comment._id);
                                }}
                              >
                                reply
                              </span>
                            </LowerCommentContainer>
                          </Comment>
                          {c.subcomments.map((sc, j) => {
                            return (
                              <SubComment key={j}>
                                <Nickname>{sc.author}</Nickname>
                                <Contents>
                                  @{sc.author}, <br /> {sc.content}
                                </Contents>
                                <LowerCommentContainer>
                                  <span>{sc.date}</span>
                                </LowerCommentContainer>
                              </SubComment>
                            );
                          })}
                        </>
                      );
                    })
                  )}
                  <ContentsInput id="commentcontent" />
                  <Confirm id="confirm">Post</Confirm>
                </CommentsBlock>
              </LowerBlock>
            </>
          )}
        </RightFrame>
      </Content>
    </>
  );
}

【问题讨论】:

  • 乍一看,您是在添加事件侦听器,但并未删除它们。此外,DOM 操作/查询是 React 中的反模式。要么使用 React ref 来访问任何 DOMNode,要么将事件处理程序直接附加到元素。现在深入挖掘。
  • 我现在尝试直接附加事件监听器,谢谢你,Drew!
  • 是的,看起来每个渲染周期都为onClick 组件添加了越来越多的onClick 侦听器。在 ifCom 中,您将它们添加到一个循环中,因此如果在初始渲染中 article.commentsArr 数组中有两个元素,您将添加 2 个侦听器。
  • 它有帮助,德鲁!现在一切正常! :)

标签: javascript reactjs react-router jsx


【解决方案1】:

试试这个event.preventDefault();

更多信息: https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault

【讨论】:

  • 谢谢你,库尔迪普!我已经解决了!但无论如何!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-10
  • 2016-12-06
  • 2011-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多