NotionAPIで画像を取得すると、1時間で期限切れになるURLの問題に直面することになります。
みなさん様々な工夫をされていますが、useSWRを使用してこの問題を回避しました。
useSWRはデータのフェッチとキャッシュを自動的に管理するReactフックですが、これを使用することでページ全体はSSGにしながら画像のURL部分のみページ表示時にレンダリングすることができます。
import { Client } from "@notionhq/client"; import React from "react"; import { List, Card, Image, Spin, Pagination } from "antd"; import { BookOutlined, EditOutlined, LinkOutlined, IdcardOutlined, LoadingOutlined, } from "@ant-design/icons"; import useSWR from "swr"; import axios from "axios"; const antIcon = ( <LoadingOutlined style={{ fontSize: 24, }} spin /> ); const fetcher = async (url) => { if (!url) return null; const response = await axios.get(url); if (response.data.type === "external") { return response.data.url; } else if (response.data.type === "file") { return response.data.file.url; } return null; }; export async function getStaticProps() { const notion = new Client({ auth: process.env.NOTION_API_KEY }); const databaseId = process.env.DATABASE_ID; const response = await notion.databases.query({ database_id: databaseId, }); const data = response.results.map((page) => { return { id: page.id, title: page.properties.title.title[0].text.content, author: page.properties.author.rich_text[0]?.text?.content || "", text: page.properties.action.rich_text[0] ? page.properties.action.rich_text[0].plain_text : "", thumbnail: page.properties.thumb && page.properties.thumb.files.length > 0 ? page.properties.thumb.files[0].file.url : null, }; }); return { props: { data }, }; } export default function Home({ data }) { const { data: imageUrl, error } = useSWR(data?.thumbnail, fetcher); return ( <div className="container py-10 mx-auto px-4 transition-all"> <h1 className="text-3xl mb-10 font-bold underline-offset-8 underline"> PageTitle </h1> <div id="scrollableDiv" className="rounded border-solid border-2 border-black-600 shadow-md px-5" > <List size="large" itemLayout="vertical"> {data.map((page, index) => ( <List.Item key={page.id}> <div className="flex gap-x-5"> <div className="min-w-[200px] relative"> <Image // preview={false} width={200} alt={page.title} src={page.thumbnail} fallback="https://placehold.jp/200x250.png" /> </div> <div className="flex-1"> <div className="text-lg font-bold mb-5 flex items-start gap-x-1"> <BookOutlined className="mt-1" /> <p>{page.title}</p> </div> <div className="space-y-1"> <p className="text-md flex gap-x-1 text-gray-600"> <EditOutlined className="mt-1" /> {page.author} </p> <p className="text-sm text-gray-600 flex gap-x-1"> <IdcardOutlined className="mt-1" /> {page.id} </p> <p className="text-sm text-gray-600 flex gap-x-1"> <LinkOutlined className="mt-1" /> ImageURL:{imageUrl ? imageUrl[index] : page.thumbnail} </p> </div> </div> </div> </List.Item> ))} </List> </div> </div> ); }