实时加载评论的问题
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 评论者会测试实时环境还是沙盒环境?