Skip to content

Commit b3637fb

Browse files
committed
fix(feed): fetch posts on client-side to avoid empty data issue during Vercel server rendering
1 parent 521a9eb commit b3637fb

2 files changed

Lines changed: 21 additions & 29 deletions

File tree

src/app/(private)/feed/layout.tsx

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,7 @@
1-
import { postsDataSchema } from "@/lib/types"
2-
import { baseUrl } from "@/lib/utils"
31
import { FeedClientWrapper } from "@/components/feed-client-wrapper"
42

5-
function PageErrorMessage() {
6-
return (
7-
<h2 className="text-center mx-auto text-primary-red">
8-
Could not get the page. Please try again in a few minutes.
9-
</h2>
10-
)
11-
}
12-
133
type FeedLayoutProps = { children: React.ReactNode }
144

155
export default async function FeedLayout({ children }: FeedLayoutProps) {
16-
const response = await fetch(baseUrl, { cache: "no-store" })
17-
18-
if (!response.ok) {
19-
return <PageErrorMessage />
20-
}
21-
22-
const data: unknown = await response.json()
23-
console.log("data:", data)
24-
const validatedData = postsDataSchema.safeParse(data)
25-
console.log("validatedData:", validatedData)
26-
return validatedData.success
27-
? <FeedClientWrapper data={validatedData.data.results}>{children}</FeedClientWrapper>
28-
: <PageErrorMessage />
6+
return <FeedClientWrapper>{children}</FeedClientWrapper>
297
}

src/components/feed-client-wrapper.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ import { useRouter } from "next/navigation"
55
import { PostsContextProvider } from "@/contexts/posts-context-provider"
66
import { useUsernameContext } from "@/lib/hooks"
77
import { Post } from "@/lib/types"
8+
import { baseUrl } from "@/lib/utils"
9+
import { postsDataSchema } from "@/lib/types"
810

9-
type ClientProtectionProps = {
10-
children: React.ReactNode
11-
data: Post[]
12-
}
11+
type ClientProtectionProps = { children: React.ReactNode }
1312

14-
export function FeedClientWrapper({ data, children }: ClientProtectionProps) {
13+
export function FeedClientWrapper({ children }: ClientProtectionProps) {
1514
const router = useRouter()
1615
const { usernameState } = useUsernameContext()
1716
const [hasMounted, setHasMounted] = useState(false)
17+
const [posts, setPosts] = useState<Post[] | null>(null)
1818

1919
useEffect(() => {
2020
setHasMounted(true)
@@ -26,6 +26,20 @@ export function FeedClientWrapper({ data, children }: ClientProtectionProps) {
2626
}
2727
}, [hasMounted, usernameState, router])
2828

29+
useEffect(() => {
30+
async function loadPosts() {
31+
const response = await fetch(baseUrl)
32+
const data: unknown = await response.json()
33+
const validatedData = postsDataSchema.safeParse(data)
34+
setPosts(validatedData.success ? validatedData.data.results : [])
35+
}
36+
loadPosts()
37+
}, [])
38+
39+
if (posts === null) {
40+
return <p className="text-center">Loading posts...</p>
41+
}
42+
2943
// no conditional null return to avoid hydration mismatch
30-
return <PostsContextProvider data={data}>{children}</PostsContextProvider>
44+
return <PostsContextProvider data={posts}>{children}</PostsContextProvider>
3145
}

0 commit comments

Comments
 (0)