Skip to content

Commit c976584

Browse files
Yushin-Lclaude
andcommitted
Fix nested replies beyond 2nd depth not rendering
- Refactor comment rendering to recursive renderThread() function - All depth levels now render correctly (indent caps at 3 levels) - Add depth prop to CommentItem for proper indentation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent ec5b30a commit c976584

2 files changed

Lines changed: 33 additions & 20 deletions

File tree

src/components/comments/CommentItem.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,20 @@ interface CommentItemProps {
99
authorProfile: Profile | null;
1010
currentUserId: string | null;
1111
isAdmin: boolean;
12+
depth: number;
1213
onEdit: (commentId: string, body: string) => Promise<unknown>;
1314
onDelete: (commentId: string) => Promise<unknown>;
1415
onReply: (body: string, parentId: string) => Promise<unknown>;
1516
}
1617

18+
const MAX_INDENT = 3;
19+
1720
export default function CommentItem({
1821
comment,
1922
authorProfile,
2023
currentUserId,
2124
isAdmin,
25+
depth,
2226
onEdit,
2327
onDelete,
2428
onReply,
@@ -47,7 +51,7 @@ export default function CommentItem({
4751
const canDelete = isOwner || isAdmin;
4852

4953
return (
50-
<div className={`py-4 ${comment.parent_id ? "ml-8 border-l-2 border-zinc-100 pl-4 dark:border-zinc-800" : ""}`}>
54+
<div className={`py-4 ${depth > 0 ? "border-l-2 border-zinc-100 pl-4 dark:border-zinc-800" : ""}`} style={depth > 0 ? { marginLeft: `${Math.min(depth, MAX_INDENT) * 1.5}rem` } : undefined}>
5155
<div className="flex items-center gap-2 text-sm">
5256
<span className="font-medium">
5357
{authorProfile?.display_name ?? "알 수 없음"}

src/components/comments/CommentSection.tsx

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,34 @@ export default function CommentSection({ postSlug }: CommentSectionProps) {
4242
});
4343
}, [comments, profiles]);
4444

45-
// Organize into threads: top-level + replies
45+
// Organize into threads
4646
const topLevel = comments.filter((c) => !c.parent_id);
47-
const replies = comments.filter((c) => c.parent_id);
4847

49-
function getReplies(parentId: string) {
50-
return replies.filter((r) => r.parent_id === parentId);
48+
function getChildren(parentId: string) {
49+
return comments.filter((c) => c.parent_id === parentId);
50+
}
51+
52+
function renderThread(parentId: string, depth: number) {
53+
const children = getChildren(parentId);
54+
if (children.length === 0) return null;
55+
return children.map((child) => (
56+
<div key={child.id}>
57+
<CommentItem
58+
comment={child}
59+
authorProfile={profiles[child.user_id] ?? null}
60+
currentUserId={user?.id ?? null}
61+
isAdmin={isAdmin}
62+
depth={depth}
63+
onEdit={edit}
64+
onDelete={remove}
65+
onReply={async (body, pid) => {
66+
if (!user) return;
67+
await add(user.id, body, pid);
68+
}}
69+
/>
70+
{renderThread(child.id, depth + 1)}
71+
</div>
72+
));
5173
}
5274

5375
return (
@@ -74,28 +96,15 @@ export default function CommentSection({ postSlug }: CommentSectionProps) {
7496
authorProfile={profiles[comment.user_id] ?? null}
7597
currentUserId={user?.id ?? null}
7698
isAdmin={isAdmin}
99+
depth={0}
77100
onEdit={edit}
78101
onDelete={remove}
79102
onReply={async (body, parentId) => {
80103
if (!user) return;
81104
await add(user.id, body, parentId);
82105
}}
83106
/>
84-
{getReplies(comment.id).map((reply) => (
85-
<CommentItem
86-
key={reply.id}
87-
comment={reply}
88-
authorProfile={profiles[reply.user_id] ?? null}
89-
currentUserId={user?.id ?? null}
90-
isAdmin={isAdmin}
91-
onEdit={edit}
92-
onDelete={remove}
93-
onReply={async (body, parentId) => {
94-
if (!user) return;
95-
await add(user.id, body, parentId);
96-
}}
97-
/>
98-
))}
107+
{renderThread(comment.id, 1)}
99108
</div>
100109
))}
101110
</div>

0 commit comments

Comments
 (0)