You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中OnClick触发renderReplies无效,点击展示回复功能异常

解决React点击展开评论回复的问题

你的问题核心是直接调用renderReplies返回JSX,但没有把这些JSX挂载到DOM中——React的渲染完全依赖状态驱动,点击事件里只执行函数不会触发重新渲染,自然看不到回复。以下是不用display: none的解决方案:

核心思路

用状态记录每个回复的展开状态,点击按钮时切换状态,React会根据状态变化自动渲染对应的回复内容。

修改后的代码

import { useState } from 'react';
import ReactMarkdown from 'react-markdown';
import ImArrowUp from 'react-icons/im';
import HiArrowNarrowRight from 'react-icons/hi';

const CommentSection = () => {
  // 用对象存储每个回复的展开状态,key用回复的唯一id
  const [expandedReplies, setExpandedReplies] = useState({});

  // 切换回复展开状态的函数
  const toggleReplyExpansion = (replyId) => {
    setExpandedReplies(prev => ({
      ...prev,
      [replyId]: !prev[replyId]
    }));
  };

  // 递归渲染回复
  const renderReplies = (comment) => {
    if (!comment.data.replies) return null;

    return (
      <div className="reply">
        {comment.data.replies.data.children.map(reply => {
          if (!reply.data.body) return null;
          const replyId = reply.data.id;
          return (
            <div className="comment-card" key={replyId}>
              <span className="comment-author">{reply.data.author}</span>
              <ReactMarkdown>{reply.data.body}</ReactMarkdown>
              <div className="upvotes">
                <ImArrowUp id="comment-arrow-icon" /> 
                {reply.data.score}
              </div>
              {/* 显示展开/收起按钮 */}
              {showMoreReplies(reply)}
              {/* 状态为展开时,渲染子回复 */}
              {expandedReplies[replyId] && renderReplies(reply)}
            </div>
          );
        })}
      </div>
    );
  };

  const showMoreReplies = (reply) => {
    if (!reply.data.replies) return null;
    const replyId = reply.data.id;
    return (
      <span 
        className="show-all-replies" 
        onClick={() => toggleReplyExpansion(replyId)}
      >
        {/* 根据状态切换按钮文本 */}
        {expandedReplies[replyId] ? 'Hide replies' : 'Show more replies'} 
        <HiArrowNarrowRight className="show-more-replies-arrow" />
      </span>
    );
  };

  // 这里替换为你的父评论渲染逻辑
  return (
    <div className="comment-section">
      {/* {parentComments.map(comment => (
        <div className="comment-card" key={comment.data.id}>
          <span className="comment-author">{comment.data.author}</span>
          <ReactMarkdown>{comment.data.body}</ReactMarkdown>
          <div className="upvotes">
            <ImArrowUp id="comment-arrow-icon" /> 
            {comment.data.score}
          </div>
          {showMoreReplies(comment)}
          {expandedReplies[comment.data.id] && renderReplies(comment)}
        </div>
      ))} */}
    </div>
  );
};

export default CommentSection;

关键修改点

  • 新增expandedReplies状态:用对象存储每个回复的展开状态,key用回复的唯一id,确保每个回复的状态独立。
  • 新增toggleReplyExpansion函数:点击按钮时切换对应回复的展开状态,触发React重新渲染。
  • 修改renderReplies:在评论卡片中,根据expandedReplies的状态决定是否渲染子回复。
  • 修改showMoreReplies:点击时调用状态切换函数,而非直接调用renderReplies,同时根据状态切换按钮文本(可选优化)。

这样实现完全由状态驱动渲染,不需要操作DOM或用display: none,适合大量评论的场景,每个回复的展开状态都是独立维护的。

内容的提问来源于stack exchange,提问作者araghast94

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 03:15:46