Skip to content

Commit b6f0802

Browse files
authored
useHydratedフックを追加し、コンテンツの読み込み中にスケルトンローディングを表示する機能を実装しました。また、不要なLoader2コンポーネントを削除しました。 (#541)
2 parents 4019636 + 87c3a6a commit b6f0802

File tree

4 files changed

+57
-45
lines changed

4 files changed

+57
-45
lines changed

web/app/components/ui/skeleton.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { cn } from "~/utils/cn";
2+
3+
function Skeleton({
4+
className,
5+
...props
6+
}: React.HTMLAttributes<HTMLDivElement>) {
7+
return (
8+
<div
9+
className={cn("animate-pulse rounded-md bg-primary/10", className)}
10+
{...props}
11+
/>
12+
);
13+
}
14+
15+
export { Skeleton };

web/app/routes/$locale+/user.$handle+/page+/$slug+/comment/components/PageCommentList.tsx

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { useFetcher } from "@remix-run/react";
22
import { MoreVertical } from "lucide-react";
3-
import { Loader2 } from "lucide-react";
4-
import { useHydrated } from "remix-utils/use-hydrated";
53
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";
64
import { Button } from "~/components/ui/button";
75
import {
@@ -33,7 +31,6 @@ export function PageCommentList({
3331
locale,
3432
}: CommentListProps) {
3533
const fetcher = useFetcher();
36-
const isHydrated = useHydrated();
3734
return (
3835
<div className="space-y-4">
3936
{pageCommentsWithUser.map((pageComment) => (
@@ -87,26 +84,20 @@ export function PageCommentList({
8784
</div>
8885
</div>
8986
<div className="mt-2 prose dark:prose-invert">
90-
{!isHydrated ? (
91-
<div className="w-full h-full flex items-center justify-center">
92-
<Loader2 className="w-10 h-10 animate-spin" />
93-
</div>
94-
) : (
95-
<MemoizedParsedContent
96-
html={pageComment.content}
97-
segmentWithTranslations={
98-
pageComment.pageCommentSegmentsWithTranslations
99-
}
100-
currentHandle={currentHandle}
101-
showOriginal={showOriginal}
102-
showTranslation={showTranslation}
103-
locale={locale}
104-
voteIntent={VoteIntent.COMMENT_SEGMENT_TRANSLATION}
105-
addTranslationFormIntent={
106-
AddTranslationFormIntent.COMMENT_SEGMENT_TRANSLATION
107-
}
108-
/>
109-
)}
87+
<MemoizedParsedContent
88+
html={pageComment.content}
89+
segmentWithTranslations={
90+
pageComment.pageCommentSegmentsWithTranslations
91+
}
92+
currentHandle={currentHandle}
93+
showOriginal={showOriginal}
94+
showTranslation={showTranslation}
95+
locale={locale}
96+
voteIntent={VoteIntent.COMMENT_SEGMENT_TRANSLATION}
97+
addTranslationFormIntent={
98+
AddTranslationFormIntent.COMMENT_SEGMENT_TRANSLATION
99+
}
100+
/>
110101
</div>
111102
</div>
112103
))}

web/app/routes/$locale+/user.$handle+/page+/$slug+/components/ContentWithTranslations.tsx

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import type { UserAITranslationInfo } from "@prisma/client";
2-
import { Loader2 } from "lucide-react";
3-
import { useHydrated } from "remix-utils/use-hydrated";
42
import { LocaleLink } from "~/components/LocaleLink";
53
import { TagList } from "~/components/TagList";
64
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";
@@ -34,8 +32,6 @@ export function ContentWithTranslations({
3432
showOriginal = true,
3533
showTranslation = true,
3634
}: ContentWithTranslationsProps) {
37-
const isHydrated = useHydrated();
38-
3935
return (
4036
<>
4137
<h1 className="!mb-0 ">
@@ -92,24 +88,18 @@ export function ContentWithTranslations({
9288
className="pt-3"
9389
intent="translatePage"
9490
/>
95-
{!isHydrated ? (
96-
<div className="w-full h-full flex items-center justify-center">
97-
<Loader2 className="w-10 h-10 animate-spin" />
98-
</div>
99-
) : (
100-
<MemoizedParsedContent
101-
html={pageWithTranslations.page.content}
102-
segmentWithTranslations={pageWithTranslations.segmentWithTranslations}
103-
currentHandle={currentHandle}
104-
showOriginal={showOriginal}
105-
showTranslation={showTranslation}
106-
locale={locale}
107-
voteIntent={VoteIntent.PAGE_SEGMENT_TRANSLATION}
108-
addTranslationFormIntent={
109-
AddTranslationFormIntent.PAGE_SEGMENT_TRANSLATION
110-
}
111-
/>
112-
)}
91+
<MemoizedParsedContent
92+
html={pageWithTranslations.page.content}
93+
segmentWithTranslations={pageWithTranslations.segmentWithTranslations}
94+
currentHandle={currentHandle}
95+
showOriginal={showOriginal}
96+
showTranslation={showTranslation}
97+
locale={locale}
98+
voteIntent={VoteIntent.PAGE_SEGMENT_TRANSLATION}
99+
addTranslationFormIntent={
100+
AddTranslationFormIntent.PAGE_SEGMENT_TRANSLATION
101+
}
102+
/>
113103
</>
114104
);
115105
}

web/app/routes/$locale+/user.$handle+/page+/$slug+/components/ParsedContent.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import parse, {
55
type DOMNode,
66
} from "html-react-parser";
77
import { memo } from "react";
8+
import { useHydrated } from "remix-utils/use-hydrated";
9+
import { Skeleton } from "~/components/ui/skeleton";
810
import type { AddTranslationFormIntent } from "~/routes/resources+/add-translation-form/route";
911
import type { VoteIntent } from "~/routes/resources+/vote-buttons";
1012
import type { SegmentWithTranslations } from "../types";
@@ -33,6 +35,20 @@ export function ParsedContent({
3335
voteIntent,
3436
addTranslationFormIntent,
3537
}: ParsedContentProps) {
38+
const isHydrated = useHydrated();
39+
if (!isHydrated) {
40+
return (
41+
// Start of Selection
42+
<div className="flex flex-col space-y-3 mt-5">
43+
{Array.from({ length: 5 }).map(() => (
44+
<Skeleton
45+
key={Math.random().toString(36).substring(2, 9)}
46+
className="w-full h-5"
47+
/>
48+
))}
49+
</div>
50+
);
51+
}
3652
const sanitizedContent = DOMPurify.sanitize(html);
3753
const doc = new DOMParser().parseFromString(sanitizedContent, "text/html");
3854

0 commit comments

Comments
 (0)