notion-sdk-js
notion-sdk-js copied to clipboard
notionhq/client and Next.js 13.4.9 with server action
I'm using notionhq/client with Next.js 13.4.9 and TypeScript for an App project and I have the following issue :
This is the function to get database :
export async function getDatabase(databaseId: string) { try { const response = await notion.databases.query({ database_id: databaseId! }) return response } catch (error: unknown) { if (isNotionClientError(error)) { switch (error.code) { case ClientErrorCode.RequestTimeout: console.log(RequestTimeout error: ${error.code}); break case APIErrorCode.ObjectNotFound: console.log(ObjectNotFound error: ${error.code}); break case APIErrorCode.Unauthorized: console.log(Unauthorized error: ${error.code}); break default: console.log(Default error: ${error.code}); break } } } }
Then, this is a function using a server action :
async function getData() { 'use server' const data = await getDatabase(databaseId!) return data }
And I call a client component like that :
<Component data={getData()} />
Now, in my component if I write console.log(data), here the response I have :
Chunk { reason: null, status: "resolved_model", value: "{...}", _response: {•••} }
To get a good response and use it, I have to write this in useEffect for example :
console.log(JSON.parse(data.value)
And now I have my array of object from Notion database and I can use it.
First of all, please provide an issue in a readable syntax.
You can write codes in ```ts <code> ``` format and your codes will be much readable.
Since your getData is an async function, therefore you need to await to retrieve data otherwise it will return a Promise.
await getData()
Note that in order to use await, the Page Component needs to be async.
// page.tsx
export default async function Home() {
// ...
Simple example:
// page.tsx
import { Client } from '@notionhq/client'
const notion = new Client({
auth: process.env.NOTION_TOKEN
})
export default async function Home() {
async function getData() {
'use server'
return await notion.databases.query({
database_id: process.env.NOTION_DATABASE_ID as string,
})
}
const data = await getData()
return (<Component data={data} />)
}
Yes, Thanks ! I updated my code and I get a right result now 👍
// page.tsx
export default async function Home() {
async function getData() {
'use server'
return await getDatabase(databaseId!)
}
const data = await getData()
async function getPageContent() {
'use server'
return await getPage(pageId!)
}
const page = await getPageContent()
async function getBlocksIntoPage() {
'use server'
const blocks = await getBlocks(pageId!)
const childBlocks = await Promise.all(
blocks!
.filter((block) => (block as any).has_children)
.map(async (block) => {
return {
id: block.id,
children: await getBlocks(block.id)
}
})
)
const blocksWithChildren = blocks?.map((block) => {
if ((block as any).has_children && !(block as any)[(block as any).type].children) {
(block as any)[(block as any).type]["children"] = childBlocks.find(
(x) => x.id === block.id
)?.children
}
return block
})
return blocksWithChildren
}
const blocks = await getBlocksIntoPage()
return (
<main>
<HomePage
data={data}
page={page}
blocks={blocks}
/>
</main>
)
}
With .has_children, the type of block (PartialBlockObjectResponse | BlockObjectResponse) is not valid. I have to write (block as any).has_children. I don't understand why ?
I've noticed some type issues in notion client also. I'm planning to open an issue for this soon.
Since has_children is in type BlockObjectResponse but not PartialBlockObjectResponse, you cannot directly access block.has_children.
For now, just pass any to block.
Example:
blocks.map((block: any) => block.has_children)
Ok, thanks ! 👍