DATA-WORLD-BLOG

post=null ? _LinkPage & MentionPage

👤horomi

image block

Original code

---
import { Post } from '../../lib/interfaces.ts'
import { getPostByPageId } from '../../lib/notion/client'
import { getPostLink } from '../../lib/blog-helpers.ts'
import '../../styles/notion-color.css'
import arrow from '../../images/icon-arrow-link.svg'
export interface Props {
  pageId: string
}
const { pageId } = Astro.props
let post: Post = null
if (pageId) {
  post = await getPostByPageId(pageId)
}
---

{
  post ? (
    <a href={getPostLink(post.Slug)} class="link">
      <>
        <span class="icon">
          {post.Icon && post.Icon.Type === 'emoji' ? (
            post.Icon.Emoji
          ) : post.Icon && post.Icon.Type === 'external' ? (
            <img src={post.Icon.Url} class="notion-icon" />
          ) : (
            '📄'
          )}
          <img src={arrow} class="icon-link" alt="" />
        </span>
        <span class="text">{post.Title}</span>
      </>
    </a>
  ) : (
    <a class="link">
      <span class="icon">
        🚫
        <img src={arrow} class="icon-link" alt="" />
      </span>
      <span class="text not-found">Post not found</span>
    </a>
  )
}
src/components/notion-blocks/Mention.astro

Fixing with ChatGPT

❓ Prompt:ifの記述の仕方

astro.jsでブログを開発しています。

記事を管理するDBを2つ用意しています。
1つのバージョンはできているところにこれから2つ目も対応しようとしています。

ifの記述の仕方を教えてください

const { pageId } = Astro.props

let post: Post = null
let subPost: SubPost = null
if (pageId) {
  post = await getPostByPageId(pageId)
}
💬 Answer

次のバージョンで2つ目の記事を管理するために、条件分岐を追加する必要があります。以下は、if 文を使用して2つ目の記事(subPost)を取得する方法の一例です。

const { pageId } = Astro.props

let post: Post = null
let subPost: SubPost = null

if (pageId) {
  if (/* 2つ目の記事の条件 */) {
    subPost = await getSubPostByPageId(pageId)
  } else {
    post = await getPostByPageId(pageId)
  }
}

上記のコードでは、最初に pageId が存在するかどうかをチェックしています。その後、2つ目の記事を取得するための条件を追加しました。条件式の部分は、実際の要件に合わせて記述する必要があります。もし2つ目の記事の条件が /* 2つ目の記事の条件 */ の部分に複雑な条件式として記述される場合は、具体的な要件を教えていただければ、より具体的なコードを提供することができます。

この例では、subPostpost の初期値を null に設定しています。条件分岐の結果、2つ目の記事が取得できれば subPost に代入され、そうでなければ post に代入されます。

❓ Prompt:提示する範囲を増やす

> 2つ目の記事の条件
という部分が分からないので、もう少し前の部分からお伝えします。


import { Post,SubPost } from '../../lib/interfaces.ts'
import { getPostByPageId,getSubPostByPageId } from '../../lib/notion/client'
import { getPostLink,getSubPostLink } from '../../lib/blog-helpers.ts'
import '../../styles/notion-color.css'
import arrow from '../../images/icon-arrow-link.svg'

export interface Props {
  pageId: string
}

const { pageId } = Astro.props

let post: Post = null
let subPost: SubPost = null
if (pageId) {
  post = await getPostByPageId(pageId)
}
💬 Answer

おっしゃる内容から、getPostByPageId関数とgetSubPostByPageId関数を使用して、それぞれ異なる条件で記事を取得する必要があるようですね。

以下は、前提としているモジュールのインポート部分を含むコードです。

import { Post, SubPost } from '../../lib/interfaces.ts'
import { getPostByPageId, getSubPostByPageId } from '../../lib/notion/client'
import { getPostLink, getSubPostLink } from '../../lib/blog-helpers.ts'
import '../../styles/notion-color.css'
import arrow from '../../images/icon-arrow-link.svg'

export interface Props {
  pageId: string
}

const { pageId } = Astro.props

let post: Post = null
let subPost: SubPost = null
if (pageId) {
  post = await getPostByPageId(pageId)
}

この場合、getPostByPageId関数とgetSubPostByPageId関数は、それぞれPost型とSubPost型のデータを返すと想定されているようです。記事の取得方法については、それぞれの関数がどのように実装されているかに依存します。

それぞれの関数が異なる条件で記事を取得する場合、以下のようなコードになるかもしれません。

import { Post, SubPost } from '../../lib/interfaces.ts'
import { getPostByPageId, getSubPostByPageId } from '../../lib/notion/client'
import { getPostLink, getSubPostLink } from '../../lib/blog-helpers.ts'
import '../../styles/notion-color.css'
import arrow from '../../images/icon-arrow-link.svg'

export interface Props {
  pageId: string
}

const { pageId } = Astro.props

let post: Post = null
let subPost: SubPost = null
if (pageId) {
  const isSubPost = /* 2つ目の記事の条件判定 */;

  if (isSubPost) {
    subPost = await getSubPostByPageId(pageId);
  } else {
    post = await getPostByPageId(pageId);
  }
}

上記のコードでは、isSubPostという変数を使って、2つ目の記事の条件判定を行っています。isSubPosttrueであればgetSubPostByPageId関数を呼び出し、subPostに記事を代入します。それ以外の場合は、getPostByPageId関数を呼び出し、postに記事を代入します。

実際の条件判定の方法について、具体的な要件を教えていただければ、より具体的なコードを提供することができます。

❓ Prompt:不明点を伝える

const isSubPost = /* 2つ目の記事の条件判定 */;
の部分がわかりません。

記事のDBは2つに分けていてそれに関する関数をsubを付けて拡張しています。

💬 Answer

申し訳ありません、理解に誤りがありました。記事のデータベースが2つに分かれており、関数もそれに応じて拡張されているとのことですね。

以下のコードは、記事データベースが2つに分かれており、getPostByPageIdgetSubPostByPageIdという関数がそれぞれ対応している場合の例です。

import { Post, SubPost } from '../../lib/interfaces.ts'
import { getPostByPageId, getSubPostByPageId } from '../../lib/notion/client'
import { getPostLink, getSubPostLink } from '../../lib/blog-helpers.ts'
import '../../styles/notion-color.css'
import arrow from '../../images/icon-arrow-link.svg'

export interface Props {
  pageId: string
}

const { pageId } = Astro.props

let post: Post = null
let subPost: SubPost = null

if (pageId) {
  const isSubPost = /* 2つ目の記事の条件判定 */;
  
  if (isSubPost) {
    subPost = await getSubPostByPageId(pageId);
  } else {
    post = await getPostByPageId(pageId);
  }
}

上記のコードでは、isSubPostという変数を使って、2つ目の記事を取得するかどうかを判定します。isSubPostの条件判定方法については、具体的な要件によって異なるでしょう。以下は、isSubPostを判定する一般的な例です。

const isSubPost = pageId.startsWith('sub');

上記の例では、pageId'sub' で始まる場合には2つ目の記事とみなしています。具体的な条件は、実際の要件に合わせて変更してください。

もし具体的な条件判定の要件を教えていただければ、より具体的なコードを提供することができます。

❓ Prompt:わからないコードを質問

const { pageId } = Astro.propsはどういう内容なのかがわかりません。

💬 Answer

すみません、説明が不十分でした。

const { pageId } = Astro.props`は、Astroフレームワークで使用されているプロパティ(`props`)から`pageId`を取り出すためのコードです。Astroでは、ページのプロパティやデータを`props`としてアクセスすることが一般的です。

Astro.propsは、現在のページのプロパティオブジェクトを表しています。その中からpageId`というプロパティを取り出しています。

例えば、以下のようなAstro.propsの例を考えてみましょう:

{
  title: "My Blog Post",
  author: "John Doe",
  pageId: "12345"
}

この場合、Astro.propsは上記のオブジェクトを表しており、const { pageId } = Astro.propsによってpageId変数に値"12345"が代入されます。

このpageIdは、後続のコードで記事のデータベースから記事を取得するために使用されます。

❓ Prompt:分かるまで深掘り

Astro.propsの中身を確認する方法を教えてください

💬 Answer

Astro.propsの中身を確認するには、console.logを使用することができます。以下はその例です。

console.log(Astro.props);

上記のコードを実行すると、コンソールにAstro.propsの内容が表示されます。

また、Astroフレームワークでは、Astroプレビューページの@astroディレクティブでdebugオプションを指定することもできます。これにより、ブラウザの開発者ツールのコンソールにAstro.propsの内容が表示されます。

---
astro: debug
---

上記のように、Astroプレビューページの先頭にastro: debugというディレクティブを追加することで、デバッグ情報が表示されます。

これらの方法を使用して、Astro.propsの中身を確認することができます。

❓ Prompt:必要なことを伝える

pageIDでは2つあるDBの判断ができないので、DB IDで判断するようにしたいです。

💬 Answer

了解しました。pageIdではなく、DBのIDを使用して判断する方法に変更する場合は、以下のようなコードになります。

import { Post, SubPost } from '../../lib/interfaces.ts'
import { getPostByPageId, getSubPostByPageId } from '../../lib/notion/client'
import { getPostLink, getSubPostLink } from '../../lib/blog-helpers.ts'
import '../../styles/notion-color.css'
import arrow from '../../images/icon-arrow-link.svg'

export interface Props {
  dbId: string // DBのIDを指定するプロパティ
}

const { dbId } = Astro.props

let post: Post = null
let subPost: SubPost = null

if (dbId) {
  const isSubPost = (dbId === 'サブ記事DBのID'); // サブ記事DBのIDを指定

  if (isSubPost) {
    subPost = await getSubPostByPageId(pageId);
  } else {
    post = await getPostByPageId(pageId);
  }
}

上記のコードでは、Astro.props内のdbIdを使用して、サブ記事のDBかどうかを判断しています。具体的なDBのIDは、isSubPostの条件判定部分で指定する必要があります。もしサブ記事のDBのIDが分かっている場合は、そのIDを指定してください。

また、DBのIDは一意の識別子であるため、他の記事と区別するために使用することができます。該当の記事DBのIDが分かっていれば、そのIDを適切な箇所に指定してください。

❓ Prompt:取り入れるかの判断は自分→次の指示

保守しやすくしたいので、やっぱり辞めます。

必ずpageIDはgetPostByPageIdかgetSubPostByIdのどちらかに接続でき、もう一方は取得できずエラーになります。

エラーにならない方を変数に登録するように書き換えてください。

const { pageId } = Astro.props

let post: Post = null
let subPost: SubPost = null
if (pageId) {
  post = await getPostByPageId(pageId)
}
💬 Answer

了解しました。指定された要件に基づいて、エラーが発生しない方の関数結果を変数に代入するようにコードを書き換えます。

const { pageId } = Astro.props

let post: Post = null
let subPost: SubPost = null
if (pageId) {
  try {
    post = await getPostByPageId(pageId)
  } catch (error) {
    subPost = await getSubPostByPageId(pageId)
  }
}

上記のコードでは、getPostByPageId関数の呼び出しをtry-catchブロックで囲みます。もしgetPostByPageId関数でエラーが発生した場合(例えば、記事が見つからない場合など)、catchブロック内のgetSubPostByPageId関数を呼び出して、subPostに結果を代入します。

このように書き換えることで、getPostByPageIdgetSubPostByPageIdのいずれかが成功することを保証し、エラーが発生しない方の結果が変数に代入されるようになります。

❓ Prompt:使いたい形が定まったら追加したい部分を伝える

これを使います!!

この場合に、getPostLinkの部分の条件分岐を追加したいです。

post ? (
    <a href={getPostLink(post.Slug)} class="link">
      <>
        <span class="icon">
          {post.Icon && post.Icon.Type === 'emoji' ? (
            post.Icon.Emoji
          ) : post.Icon && post.Icon.Type === 'external' ? (
            <img src={post.Icon.Url} class="notion-icon" />
          ) : (
            '📄'
          )}
          <img src={arrow} class="icon-link" alt="" />
        </span>
        <span class="text">{post.Title}</span>
      </>
    </a>
  ) : (
    <a class="link">
      <span class="icon">
        🚫
        <img src={arrow} class="icon-link" alt="" />
      </span>
      <span class="text not-found">Post not found</span>
    </a>
  )
💬 Answer:ズレたら途中でSTOPして次へ

getPostLinkの部分で条件分岐を追加して、postが存在する場合と存在しない場合で異なるリンクを生成することができます。以下に修正例を示します。

post ? (
  <a href={getPostLink(post.Slug)} class="link">
    <>
      <span class="icon">
        {post.Icon && post.Icon.Type === 'emoji' ? (
          post.Icon.Emoji
        ) : post.Icon && post.Icon.Type === 'external' ? (
          <img src={post.Icon.Url} class="notion-icon" />
        ) : (
          '📄'
        )}
        <img src={arrow} class="icon-link" alt="" />
      </span>
      <span class="text">{post.Title}</span>
    </>
  </a>
) : (
  <a class="link">
    <span class="icon">
      🚫
      <img src={arrow} class="icon-link" alt="" />
    </span>
    <span class="text not-found">Post not found</span>
  </a>
)

上記のコードでは

❓ Prompt:追加指示

postのときはgetPostLinkを使い、subPostの時はgetSubPostLinkを使うようにしてください

💬 Answer

了解しました。post の場合には getPostLink を使用し、 subPost の場合には getSubPostLink を使用するように、条件分岐を修正します。

post ? (
  <a href={getPostLink(post.Slug)} class="link">
    <>
      <span class="icon">
        {post.Icon && post.Icon.Type === 'emoji' ? (
          post.Icon.Emoji
        ) : post.Icon && post.Icon.Type === 'external' ? (
          <img src={post.Icon.Url} class="notion-icon" />
        ) : (
          '📄'
        )}
        <img src={arrow} class="icon-link" alt="" />
      </span>
      <span class="text">{post.Title}</span>
    </>
  </a>
) : (
  <a href={getSubPostLink(subPost.Slug)} class="link">
    <>
      <span class="icon">
        {subPost.Icon && subPost.Icon.Type === 'emoji' ? (
          subPost.Icon.Emoji
        ) : subPost.Icon && subPost.Icon.Type === 'external' ? (
          <img src={subPost.Icon.Url} class="notion-icon" />
        ) : (
          '📄'
        )}
        <img src={arrow} class="icon-link" alt="" />
      </span>
      <span class="text">{subPost.Title}</span>
    </>
  </a>
)

上記のコードでは、post の場合には getPostLink(post.Slug) を使用し、 subPost の場合には getSubPostLink(subPost.Slug) を使用しています。それぞれの条件に応じて、適切なリンクを生成するようになりました。

修正後のコードをご確認ください。もし他の条件や修正が必要であれば、具体的な要件をお教えいただければ幸いです。

❓ Prompt:まだ追加

上記に加えて、postもSubPostも該当しなかった場合に以下のコードを入れてください

<a class="link">
      <span class="icon">
        🚫
        <img src={arrow} class="icon-link" alt="" />
      </span>
      <span class="text not-found">Post not found</span>
    </a>
💬 Answer

了解しました。postsubPost も該当しない場合に、"Post not found" のメッセージを表示するコードを追加します。

修正後のコードは以下のようになります。

{post ? (
  <a href={getPostLink(post.Slug)} class="link">
    <>
      <span class="icon">
        {post.Icon && post.Icon.Type === 'emoji' ? (
          post.Icon.Emoji
        ) : post.Icon && post.Icon.Type === 'external' ? (
          <img src={post.Icon.Url} class="notion-icon" />
        ) : (
          '📄'
        )}
        <img src={arrow} class="icon-link" alt="" />
      </span>
      <span class="text">{post.Title}</span>
    </>
  </a>
) : subPost ? (
  <a href={getSubPostLink(subPost.Slug)} class="link">
    <>
      <span class="icon">
        {subPost.Icon && subPost.Icon.Type === 'emoji' ? (
          subPost.Icon.Emoji
        ) : subPost.Icon && subPost.Icon.Type === 'external' ? (
          <img src={subPost.Icon.Url} class="notion-icon" />
        ) : (
          '📄'
        )}
        <img src={arrow} class="icon-link" alt="" />
      </span>
      <span class="text">{subPost.Title}</span>
    </>
  </a>
) : (
  <a class="link">
    <span class="icon">
      🚫
      <img src={arrow} class="icon-link" alt="" />
    </span>
    <span class="text not-found">Post not found</span>
  </a>
)}

上記の修正により、postsubPost が存在しない場合に、"Post not found" のメッセージを表示するコードが追加されました。

修正後のコードをご確認ください。ご要望があれば遠慮なくお知らせください。

❓ Prompt:これできまり

表示されなかったので原因を考えました。
try catch文のところでエラーになったらsubPostに入れるという流れは、pageID自体がエラーを起こしておらず全てpostに入ってしまっているということに気づきました。

DBが2つあるものの、Astro.propsではその判定ができないので、苦肉の策で、以下のコードに修正しました。

import { Post,SubPost } from '../../lib/interfaces.ts'
import { getPostByPageId,getSubPostByPageId } from '../../lib/notion/client'
import { getPostLink,getSubPostLink } from '../../lib/blog-helpers.ts'
import '../../styles/notion-color.css'
import arrow from '../../images/icon-arrow-link.svg'

export interface Props {
  pageId: string
}

const { pageId } = Astro.props

let post: Post = null
let subPost: SubPost = null
if (pageId) {
    post = await getPostByPageId(pageId)
    subPost = await getSubPostByPageId(pageId)
}
---

{post ? (
  <a href={getPostLink(post.Slug)} class="link">
    <>
      <span class="icon">
        {post.Icon && post.Icon.Type === 'emoji' ? (
          post.Icon.Emoji
        ) : post.Icon && post.Icon.Type === 'external' ? (
          <img src={post.Icon.Url} class="notion-icon" />
        ) : (
          '📄'
        )}
        <img src={arrow} class="icon-link" alt="" />
      </span>
      <span class="text">{post.Title}</span>
    </>
  </a>
) : subPost ? (
  <a href={getSubPostLink(subPost.Slug)} class="link">
    <>
      <span class="icon">
        {subPost.Icon && subPost.Icon.Type === 'emoji' ? (
          subPost.Icon.Emoji
        ) : subPost.Icon && subPost.Icon.Type === 'external' ? (
          <img src={subPost.Icon.Url} class="notion-icon" />
        ) : (
          '📄'
        )}
        <img src={arrow} class="icon-link" alt="" />
      </span>
      <span class="text">{subPost.Title}</span>
    </>
  </a>
) : (
  <a class="link">
    <span class="icon">
      🚫
      <img src={arrow} class="icon-link" alt="" />
    </span>
    <span class="text not-found">Post not found</span>
  </a>
)}

開発環境での確認はできていて動いてはいるんですが、postとsubPostに両方入れてしまうのはプログラム的になにか不具合を起こす原因にならないかと不安です。

💬 Answer

申し訳ありません、以前の回答で混乱を招いたようです。ご指摘いただき、誤りに気づきました。

post` と `subPost` の両方にデータが入るという問題が発生しないよう、修正を行います。以下の修正済みのコードをご確認ください。

import { Post, SubPost } from '../../lib/interfaces.ts'
import { getPostByPageId, getSubPostByPageId } from '../../lib/notion/client'
import { getPostLink, getSubPostLink } from '../../lib/blog-helpers.ts'
import '../../styles/notion-color.css'
import arrow from '../../images/icon-arrow-link.svg'

export interface Props {
  pageId: string
}

const { pageId } = Astro.props

let post: Post = null
let subPost: SubPost = null

if (pageId) {
  post = await getPostByPageId(pageId)

  if (!post) {
    subPost = await getSubPostByPageId(pageId)
  }
}

---

{post ? (
  <a href={getPostLink(post.Slug)} class="link">
    <>
      <span class="icon">
        {post.Icon && post.Icon.Type === 'emoji' ? (
          post.Icon.Emoji
        ) : post.Icon && post.Icon.Type === 'external' ? (
          <img src={post.Icon.Url} class="notion-icon" />
        ) : (
          '📄'
        )}
        <img src={arrow} class="icon-link" alt="" />
      </span>
      <span class="text">{post.Title}</span>
    </>
  </a>
) : subPost ? (
  <a href={getSubPostLink(subPost.Slug)} class="link">
    <>
      <span class="icon">
        {subPost.Icon && subPost.Icon.Type === 'emoji' ? (
          subPost.Icon.Emoji
        ) : subPost.Icon && subPost.Icon.Type === 'external' ? (
          <img src={subPost.Icon.Url} class="notion-icon" />
        ) : (
          '📄'
        )}
        <img src={arrow} class="icon-link" alt="" />
      </span>
      <span class="text">{subPost.Title}</span>
    </>
  </a>
) : (
  <a class="link">
    <span class="icon">
      🚫
      <img src={arrow} class="icon-link" alt="" />
    </span>
    <span class="text not-found">Post not found</span>
  </a>
)}

修正後のコードでは、post を取得した後に、存在しない場合のみ subPost を取得するようにしました。つまり、post が存在する場合には subPost は取得されません。

これにより、postsubPost の両方にデータが入る問題が解決し、適切に記事の取得が行われます。

ご不明な点があればお知らせください。お手数ですが、修正後のコードを再度確認いただけますと幸いです。

❓ Prompt:感謝

できました!!!ありがとう

💬 Answer

どういたしまして!お役に立ててうれしいです。問題が解決し、ご満足いただけたようで良かったです。

もし他に質問やお困りごとがありましたら、いつでもお知らせください。お手伝いできることがあります。


まとめ

Astroを使用して複数のブログDBを管理する方法についての記事で、getPostLinkとgetSubPostLinkを使用して、postとsubPostの両方にデータが入る問題を解決しました。

できたーーーーーー\(^o^)/

image block

https://github.com/herohoro/MakaiZoo_astro-notion-site/pull/42