React中传递给Props的嵌套评论数据如何实现无刷新重新渲染
问题根因
嵌套回复无法自动渲染的核心原因是:你的评论全量数据存储在父组件PostView的PostCommentData状态中,Reply组件仅接收Props做纯渲染。提交嵌套回复成功后,你没有触发PostCommentData的状态更新,React检测不到数据变化自然不会触发重渲染,只有手动刷新后重新拉取接口才能拿到最新数据。
解决方案
方案1:提交后触发全量评论刷新(实现简单)
- 首先在
PostView中将拉取评论的方法抽离为可全局调用的函数,作为Props传给Reply组件:
///PostView.tsx function PostView({ match }: RouteComponentProps<MatchParams>) { const [postData, setData] = useState() const [postCommentData, setPostCommentData] = useState<[]>() const postId = match.params.id // 抽离拉取评论列表的方法 const fetchCommentList = async () => { const res = await axios.get(`/api/post/${postId}/comment`) setPostCommentData(res.data) } useEffect(() => { async function CallPostData(id: string) { const res = await axios.get(`/api/post/${id}`) setData(res.data) } CallPostData(postId) // 初始化加载评论 fetchCommentList() }, [postId]) const replyList = postCommentData?.map((item) => { return ( <Reply key={item.commentId} commentId={item.commentId} userImage={item.userImage} userName={item.userName} comment={item.comment} commentTime={item.commentTime} commentList={item.commentList} MainPostId={postId} // 给子组件传递刷新方法 refreshComment={fetchCommentList} /> ) }) }
- 改造
Reply组件,在嵌套回复提交成功后调用传入的刷新方法:
//Reply.tsx export interface IReply { commentId: number; userName: string; userImage: string; comment: string; commentTime: string; MainPostId: string; commentList: IArray[]; // 新增刷新方法类型定义 refreshComment: () => Promise<void>; } function Reply(props: IReply) { // 嵌套回复提交逻辑示例 const submitNestedReply = async (replyContent: string) => { // 调用提交嵌套回复的接口 await axios.post(`/api/comment/${props.commentId}/reply`, { content: replyContent }) // 提交成功后触发评论列表刷新 await props.refreshComment() } const Recomment = props.commentList.map((item) => { return ( <li className="childReply_item" key={item.commentId}> <div className="comment_1"> <Link to="" className="reply_thumb"> <img src={ item.userImage === null || item.userImage === "string" ? "https://myrecord.s3.ap-northeast-2.amazonaws.com/7e1436db-68ea-45c5-b997-6de46f17280b.png" : item.userImage } /> </Link> <div className="reply_box"> <Link to="" className="link_name"> <span>{item.userName}</span> </Link> <p>{item.comment}</p> <p className="date">{item.commentTime}</p> </div> </div> </li> ) }) }
方案2:本地更新状态(性能更优)
如果不想提交后额外发起一次全量评论拉取请求,可以直接在本地更新对应父评论的回复列表:
- 在
PostView中新增本地更新回复列表的方法,传给Reply组件:
// PostView.tsx 新增方法 const addNestedReply = (parentCommentId: number, newReply: IArray) => { setPostCommentData(prev => { return prev.map(comment => { if(comment.commentId === parentCommentId) { return { ...comment, commentList: [...comment.commentList, newReply] } } return comment }) }) } // 传入Reply组件 <Reply // 其他原有Props不变 addNestedReply={addNestedReply} />
- 在
Reply组件提交回复成功后,调用该方法传入当前父评论ID和接口返回的新回复数据即可,无需重新拉取全量评论。
功能示意图

内容的提问来源于stack exchange,提问作者sunpl13
相关产品推荐
相关产品推荐

