You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

React CLI中使用map和filter实现评论与回复嵌套列表

修复评论嵌套回复的层级展示问题

看起来你的核心逻辑思路是对的,但几个关键小问题导致回复没能正常渲染出来,我来帮你一步步修正:

主要问题分析

  • replyIterationMap函数缺少返回值:你在这个函数里执行了map生成JSX,但没有把结果返回出去,组件自然不会渲染任何回复内容。
  • 重复过滤数据影响性能:每次渲染评论时都遍历整个回复列表做filter,数据量大时会拖慢渲染速度,建议提前把回复整理成以comment_id为键的映射表。
  • 细节拼写错误:ReplyList里的updtaed_on是笔误(应该是updated_on),还有回复按钮的“Replay”应该是“Reply”,虽然不影响功能,但保持细节严谨更好。

修改后的完整代码

import React, { Component } from 'react';
import Moment from 'react-moment';
// 请替换成你的样式模块路径
import Style from './your-style-file';

class Comments extends Component {
  constructor(props) {
    super(props);
    this.state = {
      blogList: {},
      commentList: [
        {"id":"1","post_id":"1","username":"Rovan","content":"Wow","avatar":"","created_on":"2020-01-16","updated_on":null},
        {"id":"2","post_id":"1","username":"Ravan","content":"Woooow!","avatar":"","created_on":"2020-01-16","updated_on":null},
        {"id":"4","post_id":"1","username":"Ravan V","content":"Yes Ram","avatar":"","created_on":"2020-01-19","updated_on":null},
        {"id":"5","post_id":"1","username":"Ravan V","content":"Yes Ram","avatar":"","created_on":"2020-01-19","updated_on":null}
      ],
      // 修正拼写错误:updtaed_on → updated_on
      replyList: [
        {"id":"1","comment_id":"1","post_id":"1","username":"Sam","content":"wow","avatar":"","created_on":"2020-01-15","updated_on":null},
        {"id":"2","comment_id":"1","post_id":"1","username":"Ron","content":"Yes! Yes!","avatar":"","created_on":"2020-01-14","updated_on":null},
        {"id":"3","comment_id":"2","post_id":"1","username":"Sam","content":"wow","avatar":"","created_on":"2020-01-15","updated_on":null}
      ]
    };
    // 提前把回复转成映射表,避免重复过滤
    this.replyMap = this.state.replyList.reduce((map, reply) => {
      if (!map[reply.comment_id]) map[reply.comment_id] = [];
      map[reply.comment_id].push(reply);
      return map;
    }, {});
  }

  AvatarColorChange = (char) => {
    // 这里保留你原来的颜色切换逻辑,示例用简单的首字母取模
    const colorClasses = ['avatar-red', 'avatar-blue', 'avatar-green'];
    return colorClasses[char.charCodeAt(0) % colorClasses.length];
  };

  render() {
    const { commentList } = this.state;

    // 重构回复渲染函数,确保返回JSX数组
    const renderReplies = (commentId) => {
      const replies = this.replyMap[commentId] || [];
      return replies.map((item, index) => (
        <div className="media d-block d-md-flex mt-3" key={index}>
          <div className={`${Style.avatar} ${this.AvatarColorChange(item.username[0])}`}>
            <h2 className="text-center pt-1 mt-md-1 mt-sm-2 mt-lg-1">
              {item.username[0].toUpperCase()}
            </h2>
          </div>
          <div className="media-body text-center text-md-left ml-md-3 ml-0">
            <h5 className="mt-0 font-weight-bold">
              {item.username}
              <span className={`${Style.relativeDate} float-right font-weight-lighter`}>
                <Moment format="MMM 'DD'">{item.created_on}</Moment>
              </span>
            </h5>
            <p>{item.content}</p>
            <hr />
          </div>
        </div>
      ));
    };

    const commentIterationMap = commentList.map((item) => (
      // 用评论id作为key,比index更可靠
      <div className={`${Style.comments} media d-block d-md-flex mt-4`} key={item.id}>
        <div className={`${Style.avatar} ${this.AvatarColorChange(item.username[0])}`}>
          <h2 className="text-center pt-1 mt-md-1 mt-sm-2 mt-lg-1">
            {item.username[0].toUpperCase()}
          </h2>
        </div>
        <div className="media-body text-center text-md-left ml-md-3 ml-0">
          <h5 className="font-weight-bold">
            {item.username}
            <span className={`${Style.relativeDate} float-right font-weight-lighter`}>
              <Moment format="MMM DD">{item.created_on}</Moment>
            </span>
          </h5>
          <p>{item.content}</p>
          <div className="text-right pt-1">
            <a href="#i" id="reply"> Reply </a> {/* 修正拼写:Replay → Reply */}
          </div>
          <hr />
          {/* 调用回复渲染函数 */}
          {renderReplies(item.id)}
        </div>
      </div>
    ));

    return (
      <div className="comments">
        {commentIterationMap}
      </div>
    );
  }
}

export default Comments;

额外优化说明

  1. 组件命名规范:把原来的comments改成Comments,符合React组件首字母大写的约定。
  2. Key值优化:用评论的id代替index作为元素key,避免列表顺序变化时React误判DOM元素。
  3. 性能提升:通过reduce预生成回复映射表,减少重复遍历操作,渲染更高效。

这样修改后,评论和对应的回复就能正确嵌套展示啦!

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

火山引擎 最新活动