WordPress Native Blog Comments: How to show threaded (children) of parent comment?

Hey guys - thanks in advance for any help.

Currently I’m building a small project based on the Chakra theme. Within this theme I have native WordPress comments working properly which is great! The problem is, I cannot get the comment replies (child comments/threads) to show at all.

I have used this page as a reference: @frontity/wp-comments - API Reference but I have just not been successful in finding a way for this to show. I’m just not sure if I’m even approaching this correctly…

I can see the comment reply itself within the state.source.comment array, but I’m not sure how to display it properly below the parent. I feel like I’m definitely missing something.

Does anyone have any advice or an example of this working? I appreciate any help. :slight_smile:

Below is the link to my repo. I’m also linking straight away to the comments component for anyone to check out.

Github Repo: GitHub - Marcquito/enzosgreatadventure
Github Repo (Comments Component): enzosgreatadventure/packages/frontity-chakra-theme/src/components/comments at main · Marcquito/enzosgreat
URL of WP REST API: https://admin.enzosgreatadventure.com

Thank you!

The main issue is that a single comment doesn’t know the children, however the wp-comment package does know it. So in you first have to loop over the parent comments without doing anything other than calling the RenderComment component. In here you render the comment itself and check for children, if they exist loop back to RenderComment and handle the child comment (and their children).

I haven’t tested the below code and most likely won’t work, but should at least give an indication of how to handle it.

import React from "react";
import { connect, styled } from "frontity";
import { formatDate } from "../helpers";

const CommentsList = ({ state, libraries, postId }) => {
    const data = state.source.get(`@comments/${postId}`);
    const Html2React = libraries.html2react.Component;

    // RenderComment component
    const RenderComment = ({ comment }) => {
        const authorAvatar = state.source.comment[comment.id].author_avatar_urls['96'];
        const authorName = state.source.comment[comment.id].author_name || "Anonymous";
        const authorDate = state.source.comment[comment.id].date;
        const authorComment = state.source.comment[comment.id].content.rendered;

        return (
            <>
                <Comment>
                    <div className="author-info">
                        <div className="author-avatar">
                            <img src={authorAvatar} />
                        </div>
                        <div className="author-name">
                            {authorName}<br />
                            <small>{formatDate(authorDate)}</small>
                        </div>
                    </div>
                    <CommentContent>
                         {/* current comment */}
                        <Html2React html={authorComment} />
                    </CommentContent>
                    {/* loop over children, if they exist */}
                    {comment.children &&
                        comment.children.map(elem, index => {
                            return (
                                <RenderComment key={index} comment={elem} />
                            );
                        })
                    }
                </Comment>
            </>
        );
    };

    // set the container and loop over the main comments
    return (
        <>
            <Container>
                <h3 className="comment-section-title">Comments</h3>
                {data.items.map(elem, index => {
                    return (
                        <RenderComment key={index} comment={elem} />
                    );
                })}
            </Container>
        </>
    );
};


export default connect(CommentsList);

const Container = styled.div`
    margin: 40px;
    max-width: 750px;
    margin-left: auto;
    margin-right: auto;
    width: 92%;
    .comment-section-title{
        font-family: var(--chakra-fonts-heading);
        font-weight: var(--chakra-fontWeights-bold);
        text-transform: uppercase;
        font-size: 1.5em;
        font-weight: 600;
        margin-bottom: 20px;
    }
    .author-info{
        display: flex;
    }
    .author-info img{
        border-radius: var(--chakra-radii-full);
        margin-right: 20px;
        width: 55px;
        height: 55px;
        box-shadow: 0px 0px 25px -7px var(--chakra-colors-accent-400);
        border: 1px solid var(--chakra-colors-accent-400);
    }
    .author-name{
    }
`;

const Comment = styled.div`
    padding: 20px;
    border-bottom: 1px solid #e9f5f2;
    .author-name{
        font-weight: 800;
    }
`;

const CommentContent = styled.div`
    padding: 10px 0;
`;

Thanks for much for the direction! I spent some time working with what you have outlined here, but still having a bit of an issue having them work properly. Do you know of any examples out there I can view to see how they’re working?

The only example is from the docs page, which should work (unless they changed the package without changing the documentation.

const Comments = connect(({ postId, state }) => {
  // Get comments from state.
  const data = state.source.get(`@comments/${postId}`);

  // Utility to render comments and replies recursively.
  const renderComments = (items) =>
    items.map(({ id, children }) => (
      // You should define your own <Comment/> component!
      <Comment key={id}>
        {/* Render replies */}
        {children && renderComments(children)}
      </Comment>
    ));

  // Render comments if data is ready.
  return data.isReady ? renderComments(data.items) : null;
});

Thanks again for the help and direction on this one… still working through a few issues since for some reason this threading isn’t working properly for me. I’ll be sure to post here with an update when I get it working finally.