NotionをCMS代わりに利用して、Next.js でのサイト構築方法の相談があったので経験がなかったのでひとまず触ってみたときの備忘録です。
基礎的なことにしか触れてはいないと思います。
そもそも Notion を使うのもこれが初めて。
secret_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
なかんじのトークンが発行されるさっき追加したインテグレーションを選択する。
記事の内容は AI に書いてもらった。
yarn add @notionhq/client
NOTION_SECRET=インテグレーション追加したときに発行されたトークンを書く
NOTION_DATABASE_ID=さっき取り出したDBのIDを書く
たぶんやらなくていいことまでやってそうだけど。
# pages/news/index.tsx
import { Client } from "@notionhq/client";
import { QueryDatabaseResponse } from "@notionhq/client/build/src/api-endpoints";
import { useEffect, useState } from "react";
const notion = new Client({
auth: process.env.NOTION_SECRET,
});
export default function NewsList() {
const [data, setData] = useState<null | QueryDatabaseResponse>(null);
const get = async () => {
const res = await notion.databases.query({
database_id: process.env.NOTION_DATABASE_ID || "",
filter: {
and: [
{
property: "published",
checkbox: {
equals: true,
},
},
{
property: "category",
multi_select: {
contains: "news",
},
},
],
},
sorts: [
{
property: "date",
direction: "descending",
},
],
});
console.log({ res });
setData(res);
};
useEffect(() => {
get().then((res) => {
console.log({ res });
});
}, []);
return <div>hoge</div>;
}
→ でこれレンダリングしてみると、CORS でひっかかる。。
調べてみたけど、結果的にはちゃんと Next.js の作法に乗っかれば解決する。
型は適当にしかつけてません🙇🙇🙇
# pages/news/index.tsx
import { Client } from "@notionhq/client";
const notion = new Client({
auth: process.env.NOTION_SECRET,
});
export async function getStaticProps() {
try {
const database = await notion.databases.query({
database_id: process.env.NOTION_DATABASE_ID || "",
filter: {
and: [
{
property: "published",
checkbox: {
equals: true,
},
},
{
property: "category",
multi_select: {
contains: "news",
},
},
],
},
sorts: [
{
property: "date",
direction: "descending",
},
],
});
return {
props: {
data: database.results,
},
};
} catch (error) {
console.log("Error fetching data:", error);
return {
props: {
data: null,
},
};
}
}
export default function NewsList({ data }: { data: Object[] }) {
console.log({ data });
return (
<>
{data.map((post: any) => (
<div key={post.id}>
<a href={`/news/${post.id}`}>{post.id}</a>
</div>
))}
</>
);
}
# pages/news/[id].tsx
import { Client } from "@notionhq/client";
const notion = new Client({
auth: process.env.NOTION_SECRET,
});
export const getStaticPaths = async () => {
const database = await notion.databases.query({
database_id: process.env.NOTION_DATABASE_ID || "",
filter: {
and: [
{
property: "published",
checkbox: {
equals: true,
},
},
{
property: "category",
multi_select: {
contains: "news",
},
},
],
},
sorts: [
{
property: "date",
direction: "descending",
},
],
});
const paths = database.results.map((index) => ({
params: {
id: index.id,
},
}));
return { paths, fallback: "blocking" };
};
export async function getStaticProps({ params }: { params: { id: string } }) {
try {
const page = await notion.blocks.children.list({
block_id: params.id,
});
return {
props: {
data: page.results,
},
};
} catch (error) {
console.log("Error fetching data:", error);
return {
props: {
data: null,
},
};
}
}
export default function NewsPost({ data }: { data: Post }) {
console.log({ data });
return (
<>
{data.map((block: any, index: number) => {
if (block.heading_1) {
return (
<h1 key={index}>
{block.heading_1.rich_text[0].plain_text}
</h1>
);
}
if (block.heading_2) {
return (
<h2 key={index}>
{block.heading_2.rich_text[0].plain_text}
</h2>
);
}
if (block.paragraph) {
return (
<p key={index}>
{block.paragraph.rich_text[0].plain_text}
</p>
);
}
})}
</>
);
}
というかんじで。表示できた。
HTMLにするところはもっといいやり方がありそう。
最後までお読みいただき、ありがとうございました。
ご意見などありましたら@hippohackへDMをお願いいたします。