【问题标题】: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 alt="" 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 双倍或三倍。

【问题讨论】:

  • 你有没有试过在设置评论后改变帖子的状态?也许这就是原因。

标签: reactjs post axios jsx


【解决方案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 alt="" 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/…
    猜你喜欢
    • 2014-07-11
    • 1970-01-01
    • 1970-01-01
    • 2012-11-26
    • 1970-01-01
    • 1970-01-01
    • 2011-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多