Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

notionhq/client and Next.js 13.4.9 with server action #425

Open
jercomio opened this issue Jul 17, 2023 · 4 comments
Open

notionhq/client and Next.js 13.4.9 with server action #425

jercomio opened this issue Jul 17, 2023 · 4 comments

Comments

@jercomio
Copy link

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.

@devjiwonchoi
Copy link

devjiwonchoi commented Aug 16, 2023

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

@jercomio
Copy link
Author

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 ?

@devjiwonchoi
Copy link

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)

@jercomio
Copy link
Author

Ok, thanks ! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants