|
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