|
1 | | -'use client'; |
2 | | -import React, { useEffect, useState } from 'react'; |
3 | | -import { useSession } from 'next-auth/react'; |
4 | | -import { useRouter, useParams } from 'next/navigation'; |
5 | | -import { PostTypes } from '@/types/postTypes'; |
6 | | -import Post from '@/components/Post'; |
| 1 | +import React from 'react'; |
7 | 2 | import fetchOnePost from './actions/fetchOnePost'; |
8 | | -import { AnimatePresence, motion } from 'framer-motion'; |
9 | | -import Head from 'next/head'; |
| 3 | +import PostPage from './PostPage'; |
| 4 | +import { notFound } from 'next/navigation'; |
10 | 5 |
|
| 6 | +const tankaToString = (tanka: string[]) => { |
| 7 | + return tanka.join(' '); |
| 8 | +}; |
| 9 | + |
| 10 | +export const generateMetadata = async (context: { params: Promise<{ postId: string }> }) => { |
| 11 | + const params = await context.params; |
| 12 | + |
| 13 | + const post = await fetchOnePost({ |
| 14 | + postId: params.postId, |
| 15 | + iconUrl: '', |
| 16 | + }); |
| 17 | + |
| 18 | + if (!post) return { title: '投稿が見つかりません' }; |
| 19 | + |
| 20 | + return { |
| 21 | + title: `Tankalizer: ${post.user.name}さんの短歌`, |
| 22 | + description: tankaToString(post.tanka), |
| 23 | + }; |
| 24 | +}; |
11 | 25 | /** |
12 | 26 | * 指定されたIDの投稿を表示する. |
13 | 27 | * @async |
14 | 28 | * @function Post |
15 | 29 | * @returns {JSX.Element} プロフィールを表示するReactコンポーネント |
16 | 30 | */ |
17 | | -const PostPage = () => { |
18 | | - const { postId } = useParams() as { postId: string }; |
19 | | - const [post, setPost] = useState<PostTypes | null>(null); |
20 | | - // セッションの取得 |
21 | | - const session = useSession(); |
22 | | - const router = useRouter(); |
| 31 | +const Page = async (context: { params: Promise<{ postId: string }> }) => { |
| 32 | + const params = await context.params; |
23 | 33 |
|
24 | | - // 投稿IDから投稿をFetchする |
25 | | - useEffect(() => { |
26 | | - const getPost = async () => { |
27 | | - if (!postId) return; |
28 | | - if (session.status === 'loading') return; |
29 | | - const data = await fetchOnePost({ |
30 | | - postId: postId as string, |
31 | | - iconUrl: session.data?.user?.image ?? '', |
32 | | - }); |
33 | | - if (!data) router.push('/post-not-found'); |
34 | | - setPost(data); |
35 | | - }; |
36 | | - getPost(); |
37 | | - }, [postId, session.data?.user?.image, session.status, router]); |
| 34 | + const post = await fetchOnePost({ |
| 35 | + postId: params.postId, |
| 36 | + iconUrl: '', |
| 37 | + }); |
38 | 38 |
|
39 | | - const tankaToString = (tanka: string[]) => { |
40 | | - return tanka.join('\n'); |
41 | | - }; |
| 39 | + if (!post) notFound(); |
42 | 40 |
|
43 | 41 | return ( |
44 | 42 | <div> |
45 | | - {post && ( |
46 | | - <Head> |
47 | | - <title>Tankalizer:{`${post.user.name}さんの短歌`}</title> |
48 | | - <meta name='description' content={tankaToString(post.tanka)} /> |
49 | | - </Head> |
50 | | - )} |
51 | | - |
52 | | - {!post && <p className='py-3 text-center'>短歌を取得中...</p>} |
53 | | - <AnimatePresence mode='wait'> |
54 | | - {post && ( |
55 | | - <motion.div |
56 | | - initial={{ opacity: 0 }} |
57 | | - animate={{ opacity: 1 }} |
58 | | - exit={{ opacity: 0 }} |
59 | | - transition={{ duration: 0.5 }} |
60 | | - className='mx-auto max-w-sm pt-5 lg:max-w-lg' |
61 | | - > |
62 | | - {post && <Post post={post} onDelete={() => router.push('/')} />} |
63 | | - </motion.div> |
64 | | - )} |
65 | | - </AnimatePresence> |
| 43 | + <PostPage post={post} /> |
66 | 44 | </div> |
67 | 45 | ); |
68 | 46 | }; |
69 | 47 |
|
70 | | -export default PostPage; |
| 48 | +export default Page; |
0 commit comments