React Hooks实现新增评论后组件无刷新更新方案问询
嘿,我来帮你搞定这个评论提交后自动刷新又不触发无限循环的问题!核心思路是不要依赖useEffect的自动触发,而是在评论提交成功后主动调用数据更新函数,这样既能实现评论实时显示,又不会陷入无限循环的坑。
解决方案步骤
- 提取重复调用的获取数据函数:把Page组件里获取帖子和评论的axios请求封装成一个独立函数,方便后续重复调用;
- 将更新函数传递给子组件:把这个获取数据的函数传给CreateComment组件,让它在评论提交成功后触发更新;
- 仅在组件挂载时初始化数据:保持useEffect的空依赖数组,只在页面加载时获取一次初始数据,避免无意义的重复请求。
修改后的代码示例
Page.js 调整后的代码
import React, { useState, useEffect } from 'react'; import { useParams } from 'react-router-dom'; import axios from 'axios'; import '../CSS/Page.css'; import CreateComment from './CreateComment'; const Page = () => { const [show, setShow] = useState({ commentBox: false }); const [post, setPost] = useState({ id: '', username: '', title: '', body: '', date: '', comments: [{}] }); let { postTitle } = useParams(); // 封装获取帖子数据的函数 const fetchPost = async () => { try { const res = await axios.get( `http://localhost:2000/apiEndpoint/singlePost/${postTitle}`, { withCredentials: true, headers: { 'Content-Type': 'application/json' } } ); // 直接赋值完整的post对象,简化代码 setPost(res.data); } catch (err) { console.error('获取帖子数据失败:', err); } }; // 组件挂载时初始化数据 useEffect(() => { fetchPost(); }, []); // 空依赖数组,仅执行一次 const handleCommentButton = (e) => { setShow({ ...show, commentBox: !show.commentBox }); }; return ( <div className='postContainer'> <div className='singlePostcontainer'> <div className='singlePost'> <h1>{post.title}</h1> <hr /> <p>{post.body}</p> {post.id} <hr /> <h5> Comments: <button className='btnCom' onClick={handleCommentButton}> {show.commentBox ? 'Close' : 'Add Comment'} </button> </h5> {/* 将更新函数传递给CreateComment组件 */} {show.commentBox ? ( <CreateComment post={post} onCommentSubmit={fetchPost} /> ) : ( '' )} {post.comments.map((comment) => { const commentID = comment._id; return ( <div className='comment' key={commentID}> <h3>{comment.body}</h3> <h6>By: {comment.creater}</h6> </div> ); })} </div> </div> </div> ); }; export default Page;
CreateComment.js 调整后的代码
import React, { useState } from 'react'; import axios from 'axios'; const CreateComment = (props) => { const [comment, setComment] = useState({ body: '' }); const handleSubmitA = (e) => { e.preventDefault(); axios .post( `http://localhost:2000/apiEndpoint/CREATE/comment/${props.post.id}`, { body: comment.body }, { withCredentials: true, headers: { 'Content-Type': 'application/json' } } ) .then((res) => { console.log('评论提交成功:', res); // 触发父组件的数据更新 props.onCommentSubmit(); // 清空评论输入框,提升用户体验 setComment({ body: '' }); }) .catch((err) => { console.error('评论提交失败:', err); }); }; const handleChangeA = (e) => { const { name, value } = e.target; setComment({ ...comment, [name]: value }); }; return ( <div className='commentContainer'> <form onSubmit={handleSubmitA}> <label>Enter Comment</label> <textarea name="body" value={comment.body} onChange={handleChangeA} ></textarea> <button>Submit</button> </form> </div> ); }; export default CreateComment;
为什么这个方案能解决问题?
- 原来的无限循环是因为如果把
post放进useEffect的依赖数组,每次setPost都会触发useEffect重新请求数据,进而再次setPost,形成闭环; - 现在我们只在组件挂载时和评论提交成功时主动调用
fetchPost,完全由业务逻辑触发更新,不会产生无意义的重复请求,自然也就避免了无限循环。
内容的提问来源于stack exchange,提问作者KenwaySharma
相关产品推荐
相关产品推荐

