
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>
);
}