实时加载评论的问题

Posted

技术标签:

【中文标题】实时加载评论的问题【英文标题】:Issues loading comments in Realtime 【发布时间】:2021-06-09 04:43:29 【问题描述】:

我有一个社交媒体应用程序,我希望它像 facebook 一样运行,您可以在其中发表评论并实时加载评论,而无需刷新浏览器来显示评论。我能够将数据从 React 发送到后端服务器,并且能够通过 axios http 请求获取该数据,但我必须刷新浏览器才能看到显示的评论。我也不止一次看到评论显示。我没有收到任何错误,但评论不是帖子独有的,因为它是一个加载帖子的数组。我的代码有误吗?

这是前端代码。

import React,  useState, useEffect  from "react";
import Container from "react-bootstrap/Container";
import Card from "react-bootstrap/Card";
import Button from "react-bootstrap/Button";
import axios from "axios";
import "./css/sharewall.css";

const ComponentName = () => 
  const [posts, setPosts] = useState([]);
  const [comment, setComment] = useState("");
  const [id, setId] = useState("");

  const loadData = async () => 
    try 
      let res = await axios.get(`http://localhost:5000/getall`);
      setPosts(res.data);
     catch (error) 
      console.log(error);
    
  ;

  function makeRequest(e) 
    e.preventDefault();
    axios(
      method: "POST",
      url: "http://localhost:5000/postinput",
      data: 
        comment: comment,
      ,
    ).then((res) => 
      setComment(res.data.comment);
      console.log(res.data);
    );
  

  const loadComment = async () => 
    try 
      let res = await axios.post("http://localhost:5000/postinput");
      setComment(res.data.comment._id);
      console.log(res.data.comment._id)
     catch (error) 
      console.log(error);
    
  ;

  useEffect(() => 
    loadData();
  , []);

  return (
    <div className="compoentclass">
      <Container className="mt-5 ml-auto mr-auto">
        <div className="text-center">
          posts.map((post, index) => (
            <div>
              <Card className="">
                <Card.Img  src=post.url />
                <Card.ImgOverlay className="overlay">
                  <Card.Title className="text-center mt-5">
                    <Card.Text className="cardStyle text-light">
                      post.body
                    </Card.Text>
                  </Card.Title>
                </Card.ImgOverlay>
              </Card>
              posts.map((post, index) => (
              <div><Card.Text>post.comment</Card.Text></div>
              ))
              <textarea
              className="comment text-center mt-3 mb-3"
              onChange=e => setComment(e.target.value)
              value=comment
              name="comment"
              type="text"
            />
              <div className="d-flex justify-content-start mt-n3 mb-4">
                <Button
                  className="shareButton"
                  variant="secondary"
                  onClick=makeRequest
                  onChange=loadComment
                >
                  Comment
                </Button>
              </div>
            </div>
          ))
        </div>
      </Container>
    </div>
  );
;

export default ComponentName;

这是来自 cmets 的渲染,cmets 双倍或三倍。

【问题讨论】:

你有没有试过在设置评论后改变帖子的状态?也许这就是原因。 【参考方案1】:

为了让其他用户(发表评论的用户应该能够很容易地立即看到评论)实时看到 cmets,您必须对服务器/数据库实施某种“监听器”来监听新的 cmets。否则,我的浏览器怎么知道你刚刚发表了评论?看看socket.io,很容易实现。

【讨论】:

【参考方案2】:

我在您的代码中添加了一些内容,请参阅 cmets。 首先,您似乎可以在每次单击“评论”按钮时使用useEffect 重新渲染您的 cmets。要处理更新,您可以像我一样创建一个新状态。 可能您在使用多 cmets 时遇到问题,因为您的 posts 数组内部包含多个元素。在内部渲染它 maps 通过所有 posts 数组并显示每个元素。 另外,如果您在 codeandbox.io 或类似文件中重新创建代码会更好。

import React,  useState, useEffect  from "react";
import Container from "react-bootstrap/Container";
import Card from "react-bootstrap/Card";
import Button from "react-bootstrap/Button";
import axios from "axios";
import "./css/sharewall.css";

const ComponentName = () => 
  const [posts, setPosts] = useState([]);
  const [comment, setComment] = useState("");
  const [id, setId] = useState("");

  //state for resending load request
  const [isCommentFetched, setCommentFetched] = useState(false);

  const loadData = async () => 
    try 
      let res = await axios.get(`http://localhost:5000/getall`);
      setPosts(res.data);
     catch (error) 
      console.log(error);
    
  ;

  function makeRequest(e) 
    e.preventDefault();
    axios(
      method: "POST",
      url: "http://localhost:5000/postinput",
      data: 
        comment: comment,
      ,
    ).then((res) => 
      setComment(res.data.comment);
      setCommentFetched(true)
      console.log(res.data);
    )
    //don't forget to catch errors
    .catch((err)=>
    console.log(err)
    )
  

  const loadComment = async () => 
    try 
      let res = await axios.post("http://localhost:5000/postinput");
      setComment(res.data.comment._id);
      console.log(res.data.comment._id);
     catch (error) 
      console.log(error);
    
  ;

  useEffect(() => 
    loadData();
  , []);

//hook fires whenever your isCommentFetched state updating. 
  useEffect(() => 
      // if isCommentFetched true, it will send request for get new posts, and will update your comments in render.
    if(isCommentFetched)
        loadData();
    
  , [isCommentFetched]);

  return (
    <div className="compoentclass">
      <Container className="mt-5 ml-auto mr-auto">
        <div className="text-center">
          posts.map((post, index) => (
            <div>
              <Card className="">
                <Card.Img  src=post.url />
                <Card.ImgOverlay className="overlay">
                  <Card.Title className="text-center mt-5">
                    <Card.Text className="cardStyle text-light">
                      post.body
                    </Card.Text>
                  </Card.Title>
                </Card.ImgOverlay>
              </Card>
              posts.map((post, index) => (
                <div>
                  <Card.Text>post.comment</Card.Text>
                </div>
              ))
              <textarea
                className="comment text-center mt-3 mb-3"
                onChange=(e) => setComment(e.target.value)
                value=comment
                name="comment"
                type="text"
              />
              <div className="d-flex justify-content-start mt-n3 mb-4">
                <Button
                  className="shareButton"
                  variant="secondary"
                  onClick=makeRequest
                  onChange=loadComment
                >
                  Comment
                </Button>
              </div>
            </div>
          ))
        </div>
      </Container>
    </div>
  );
;

export default ComponentName;

【讨论】:

你的回答很完美!谢谢,只是想知道您是否知道一种更好的方法来编写不卡在数组中的 cmets 代码?目前,这是我可以让 cmets 在每个帖子中显示的唯一方法 其中包含对象的数组非常适合显示 cmets [,,]。每个对象元素都是具有唯一 ID 的不同注释。您可以通过映射它们来显示每个元素,并且看起来您通过映射做得很好。但是你为什么要在第一张地图中进行第二次映射呢?也许有问题。您可以查看我的沙箱,它重新创建了树形结构的 cmets。多次操作后的数组本身如下所示:[,,]。使用递归逻辑渲染。 codesandbox.io/s/loving-elbakyan-kgwuk?file=/src/…

以上是关于实时加载评论的问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 angularjs 和 socket.io 实时保存和显示评论

iOS 应用内购买:Apple 评论者会测试实时环境还是沙盒环境?

使用 AJAX 和 SQL 实时监控数据库更新

facebook api获得实时评论

JavaScript ExpressionEngine的实时评论预览

发布评论后,Django Ajax div 未重新加载/消失