footerタグを付けた記事を記事一覧から除外し、
通常の記事と別の扱いをする改造を依頼された
`getAllPosts`からデータを使用シーンによって
呼び出しやすいよう小分けになって関数が準備されている。
export async function getAllPosts(): Promise<Post[]> {
if (postsCache !== null) {
return Promise.resolve(postsCache)
}
const params: requestParams.QueryDatabase = {
database_id: DATABASE_ID,
filter: {
and: [
{
property: 'Published',
checkbox: {
equals: true,
},
},
{
property: 'Date',
date: {
on_or_before: new Date().toISOString(),
},
},
],
},
sorts: [
{
property: 'Date',
direction: 'descending',
},
],
page_size: 100,
}
let results: responses.PageObject[] = []
while (true) {
const res = (await client.databases.query(
params as any // eslint-disable-line @typescript-eslint/no-explicit-any
)) as responses.QueryDatabaseResponse
results = results.concat(res.results)
if (!res.has_more) {
break
}
params['start_cursor'] = res.next_cursor as string
}
postsCache = results
.filter((pageObject) => _validPageObject(pageObject))
.map((pageObject) => _buildPost(pageObject))
return postsCache
}`getAppPosts`をベースに呼び出している関数
実際に使われている場所の特定は、
src / pages 内のimport{} を確認すれば分かるとして….

今回依頼された「footerタグを付けた記事は除外する」のに該当する関数と該当しない関数を整理する必要がある。
| 用途 | footerで使う? | |
| getPosts | 記事一覧で10件取得 | 🙅♀ |
| getRankedPosts | Rankプロパティの値でsortさせて記事を10件取得 | 🙅♀ |
| getPostBySlug | Slugプロパティで指定された記事を1件取得 | ⭕ |
| getPostByPageId | メンションブロックで記事を指定する時に使う | ⭕ |
| getPostsByTag | 任意のタグを持つ記事を10件取得 | 🙅♀ |
| getPostsByPage | 記事一覧の2ページ目以降の記事 | 🙅♀ |
| getPostsByTagAndPage | タグ一覧ページの2ページ目以降の記事 | 🙅♀ |
| getNumberOfPages | 記事一覧ページのページ数 | 🙅♀ |
| getNumberOfPagesByTag | タグ一覧ページのページ数 | 🙅♀ |
| getAllTags | Tagプロパティに登録されてるタグ | 🙅♀ |
footerで使わない関数をどうやって除外するか….がこの記事の本題w
astro.jsで開発しているブログで、特定のTag名以外を表示させる修正をしています。
修正して表示してみるとfooterの記事を含んでしまっているようです。
```
export async function getPosts(pageSize = 10): Promise<Post[]> {
const allPosts = await getAllPosts()
return allPosts
.filter((post) => !!post.Tags.map((tag) => tag.name !== 'footer'))
.slice(0, pageSize)
}
```
提供されたコードの問題は、filterメソッド内でmapメソッドを使用している点にあります。mapメソッドは元の配列の要素を変換するのに使用され、その結果は新しい配列として返されます。この場合、各postのTagsプロパティが新しいブール値の配列に変換されます。しかし、それらのブール値が直接フィルタリングに使用されていません。なので、結果として全てのpostがフィルタリングを通過してしまいます。
この問題を解決するには、filterメソッドを使う代わりにsomeまたはeveryメソッドを使用することをお勧めします。これらのメソッドはブール値を返すため、フィルタリングに適しています。
someメソッドは配列のいずれかの要素が条件を満たす場合にtrueを返します。everyメソッドは配列のすべての要素が条件を満たす場合にtrueを返します。あなたの要件(特定のタグ(ここでは'footer')を持たない投稿だけを取得したい)に合わせて、someメソッドを使用して修正を試みてみてください。以下に修正案を示します:
export async function getPosts(pageSize = 10): Promise<Post[]> {
const allPosts = await getAllPosts()
return allPosts
.filter((post) => !post.Tags.some((tag) => tag.name === 'footer'))
.slice(0, pageSize)
}このコードは、タグの名前が'footer'であるものが一つでも存在する場合、someメソッドがtrueを返すようになります。そのtrue値を否定(!)することで、'footer'タグを持つ投稿がフィルタリングから除外されます。
試しに`getPosts`を使って
記事一覧にfooterの記事が表示されるか確認してみると….
NotionDBにTagsプロパティにfooter を追加

↓

footerの記事はカットされた\(^o^)/
無事Supportできてる様子なので、
他の関数にも取り入れてこう〜〜〜
他の関数も取り入れたいです。
でも、filterが入ってるためどこを修正すべきか判断しかねています。
export async function getRankedPosts(pageSize = 10): Promise<Post[]> {
const allPosts = await getAllPosts()
return allPosts
.filter((post) => !!post.Rank)
.sort((a, b) => {
if (a.Rank > b.Rank) {
return -1
} else if (a.Rank === b.Rank) {
return 0
}
return 1
})
.slice(0, pageSize)
}
こちらのgetRankedPosts関数では、Rankフィールドを持つ投稿のみをフィルタリングし、その後Rankフィールドの降順でソートしています。ここに「"footer" タグを除外する」機能を追加したいという理解で良いでしょうか?
その場合、以下のように修正できます:
export async function getRankedPosts(pageSize = 10): Promise<Post[]> {
const allPosts = await getAllPosts()
return allPosts
.filter((post) => !!post.Rank && !post.Tags.some((tag) => tag.name === 'footer'))
.sort((a, b) => {
if (a.Rank > b.Rank) {
return -1
} else if (a.Rank === b.Rank) {
return 0
}
return 1
})
.slice(0, pageSize)
}このコードでは、filterメソッド内で2つの条件をチェックしています:
!!post.Rank)!post.Tags.some((tag) => tag.name === 'footer'))これにより、「Rankを持つ」かつ「'footer'タグを持たない」投稿のみがフィルタリングを通過するようになります。
できました!!
今度は自分で修正してみました。
正しいかをアドバイスしてください。
修正前:
export async function getPostBySlug(slug: string): Promise<Post | null> {
const allPosts = await getAllPosts()
return allPosts.find((post) => post.Slug === slug) || null
}修正後:
export async function getPostBySlug(slug: string): Promise<Post | null> {
const allPosts = await getAllPosts()
return (
allPosts
.filter((post) => !post.Tags.some((tag) => tag.name === 'footer'))
.find((post) => post.Slug === slug) || null
)
}提出された修正は正しいです!
あなたの修正されたコードでは、まずgetAllPosts関数を使用して全ての投稿を取得しています。その後、filterメソッドを使用して'footer'タグを持つ投稿を除外します。そして、findメソッドを使用して指定されたスラッグに一致する投稿を探します。この修正により、'footer'タグを持つ投稿が返されることはありません。
ただし、この変更により一つ注意点があります。それは、「Slugが一致する投稿が'footer'タグを持っている場合、その投稿は結果から除外される」ことです。もしそれが意図した挙動であれば、あなたの修正は完全に正しいです。
以下が修正されたコードです:
export async function getPostBySlug(slug: string): Promise<Post | null> {
const allPosts = await getAllPosts()
return (
allPosts
.filter((post) => !post.Tags.some((tag) => tag.name === 'footer'))
.find((post) => post.Slug === slug) || null
)
}この修正があなたの求める動作を満たしている場合、それをそのまま使用しても問題ありません。
忘れてました!この関数は除外してはいけないものでしたね!
教えてくれてありがとう
どういたしまして!修正が不要な関数についてはそのまま保持することは全く問題ありません。各関数が求められる動作を適切に満たすように、必要に応じてコードを修正することが重要です。
何か他にご質問や助けが必要な点がございましたら、いつでもお気軽にお申し付けください。プログラミングにおける問題解決をお手伝いすることが私の役目です。
関数の内容を確認し、不要だとわかったので修正してみました。
正しいかどうかを教えてください。
修正前:
export async function getPostsByTag(
tagName: string,
pageSize = 10
): Promise<Post[]> {
if (!tagName) return []
const allPosts = await getAllPosts()
return allPosts
.filter((post) => post.Tags.find((tag) => tag.name === tagName))
.slice(0, pageSize)
}
修正後:
export async function getPostsByTag(
tagName: string,
pageSize = 10
): Promise<Post[]> {
if (!tagName) return []
const allPosts = await getAllPosts()
return allPosts
.filter(
(post) =>
!post.Tags.some((tag) => tag.name === 'footer') &&
post.Tags.find((tag) => tag.name === tagName)
)
.slice(0, pageSize)
}
提出された修正は正しいです!ただし、findメソッドの使用について一点提案があります。
あなたの修正されたコードでは、まずgetAllPosts関数を使用して全ての投稿を取得しています。その後、filterメソッドを使用して以下の条件を満たす投稿を選択しています:
!post.Tags.some((tag) => tag.name === 'footer'))post.Tags.find((tag) => tag.name === tagName))ただし、2つ目の条件でfindメソッドを使用していますが、someメソッドの方がより適しているかもしれません。findメソッドは配列の中から条件に一致する最初の要素を返しますが、このコードではその要素自体は利用されていません。一方、someメソッドは配列の中に条件に一致する要素が存在するかどうかを判定し、存在する場合はtrueを返します。
したがって、以下のように修正することを提案します:
export async function getPostsByTag(
tagName: string,
pageSize = 10
): Promise<Post[]> {
if (!tagName) return []
const allPosts = await getAllPosts()
return allPosts
.filter(
(post) =>
!post.Tags.some((tag) => tag.name === 'footer') &&
post.Tags.some((tag) => tag.name === tagName)
)
.slice(0, pageSize)
}この修正があなたの求める動作を満たしている場合、それをそのまま使用しても問題ありません。
本家のコードをなるべく使っておくことで保守が簡単になるので、findの部分はそのままにしようと思います。アドバイスありがとう
そうですね、ある程度既存のコードを維持することは、将来的な保守性やコードの一貫性を保つ上で重要です。findメソッドも確かにその要件を満たしているので、そのまま使用するのも良い選択です。
私の提案は単なるオプションであり、必ずしもそれに従う必要はありません。あなたのプロジェクトの要件とコードベースの文脈に最も合致する選択をすることが最も重要です。
他に何かご質問があればいつでもお知らせください。お手伝いすることができれば幸いです。
`!post.Tags.some((tag) => tag.name === 'footer') `を`post.Tags.some((tag) => tag.name === tagName)`の前に入れるのと、後に入れるのとではパフォーマンスは変わりますか?
はい、パフォーマンスに影響を及ぼす可能性があります。
JavaScriptの論理演算子は「短絡評価(Short-circuit evaluation)」を行います。つまり、&&(AND)演算子については、最初の条件がfalseであれば、JavaScriptは二つ目の条件を評価せずに全体の結果をfalseとします。これは||(OR)演算子についても同様で、最初の条件がtrueであれば、二つ目の条件は評価されません。
したがって、!post.Tags.some((tag) => tag.name === 'footer') && post.Tags.some((tag) => tag.name === tagName)という表現では、最初の条件がfalse(つまり、postがfooterタグを持っている)であれば、二つ目の条件は評価されません。
そのため、一般的には、計算コストが低い、またはfalseになりやすい条件を先に配置すると、全体の評価が早く終わる可能性が高まり、パフォーマンスが向上します。
ただし、このパフォーマンスの違いは、大抵の場合、非常に微小であり、特に投稿やタグの数が多くない場合、顕著な違いとはなりません。ですので、コードの可読性や保守性といった要素を優先することも重要です。
ありがとうございます。
可読性や保守を意識して修正してみました。
正しいかを教えてください。
修正前:
export async function getNumberOfPages(): Promise<number> {
const allPosts = await getAllPosts()
return (
Math.floor(allPosts.length / NUMBER_OF_POSTS_PER_PAGE) +
(allPosts.length % NUMBER_OF_POSTS_PER_PAGE > 0 ? 1 : 0)
)
}修正後:
export async function getNumberOfPages(): Promise<number> {
const allPosts = await getAllPosts()
const outOfFooterPosts = allPosts.filter(
(post) => !post.Tags.some((tag) => tag.name === 'footer')
)
return (
Math.floor(outOfFooterPosts.length / NUMBER_OF_POSTS_PER_PAGE) +
(outOfFooterPosts.length % NUMBER_OF_POSTS_PER_PAGE > 0 ? 1 : 0)
)
}あなたの修正は完全に正しいです!
修正後のコードでは、まずgetAllPosts関数を使って全ての投稿を取得し、その後filterメソッドを使って'footer'タグを持つ投稿を除外します。この修正後のリストの長さを用いてページ数を計算します。
したがって、この修正により'footer'タグを持つ投稿がページ数の計算から除外されます。
以下が修正後のコードです:
export async function getNumberOfPages(): Promise<number> {
const allPosts = await getAllPosts()
const outOfFooterPosts = allPosts.filter(
(post) => !post.Tags.some((tag) => tag.name === 'footer')
)
return (
Math.floor(outOfFooterPosts.length / NUMBER_OF_POSTS_PER_PAGE) +
(outOfFooterPosts.length % NUMBER_OF_POSTS_PER_PAGE > 0 ? 1 : 0)
)
}このコードがあなたの求める動作を満たしている場合、それをそのまま使用しても問題ありません。
関数名をoutOfFooterPostsにしていますが、今後footer以外の用途で除外したいTagが発生することも加味して、もっと分かりやすい関数名にしたいです。
すみません、私が誤解を生んでしまったようです。outOfFooterPostsはここでは一時変数の名前として使っていますね。そしてその変数名が将来的に他のタグをフィルターする際に役立つような名前にしたいという理解で合っていますか?
もしその理解が正しければ、変数名をfilteredPostsやselectedPostsのように一般的な名前に変更すると、将来的に他のタグでフィルタリングを行う場合にもその名前が適用できます。
修正後のコードは以下のようになります:
export async function getNumberOfPages(): Promise<number> {
const allPosts = await getAllPosts()
const filteredPosts = allPosts.filter(
(post) => !post.Tags.some((tag) => tag.name === 'footer')
)
return (
Math.floor(filteredPosts.length / NUMBER_OF_POSTS_PER_PAGE) +
(filteredPosts.length % NUMBER_OF_POSTS_PER_PAGE > 0 ? 1 : 0)
)
}ここでのfilteredPostsは、元の投稿リストから'footer'タグを持つ投稿を除外した結果を保持する一時的な変数です。この変数名は一般的な名前であり、他の任意のタグでフィルタリングを行う場合でもその名前が適用できます。
Tag名で除外するという意味を含めた関数名にしたいです。
コードの提示は不要です。関数名の候補を5つ教えてください
変数名に除外するタグ名を指定する意味を含めることは、その変数が何を表しているのかを明示的にするのに役立ちます。以下にいくつかの候補を示します:
excludedTagPostspostsWithoutSpecifiedTagfilteredByTagPostspostsExcludingTagnonTaggedPostsこれらの名前はすべて、特定のタグを含まない投稿の集合を表すことを示しています。ただし、これらの名前は一般的な意味を持っており、どのタグが除外されているのかは明示していません。変数名に具体的なタグ名を含める場合は、コードの可読性と保守性のバランスを取る必要があります。
postsWithoutSpecifiedTagが分かりやすいと思いました
素晴らしい選択です!postsWithoutSpecifiedTagという名前は、その変数が特定のタグを除外した投稿の集合を保持していることを明示的に示しています。これはコードを読む人にとって非常に理解しやすいでしょう。
以下のように修正できます:
export async function getNumberOfPages(): Promise<number> {
const allPosts = await getAllPosts()
const postsWithoutSpecifiedTag = allPosts.filter(
(post) => !post.Tags.some((tag) => tag.name === 'footer')
)
return (
Math.floor(postsWithoutSpecifiedTag.length / NUMBER_OF_POSTS_PER_PAGE) +
(postsWithoutSpecifiedTag.length % NUMBER_OF_POSTS_PER_PAGE > 0 ? 1 : 0)
)
}この修正があなたの求める動作を満たしている場合、それをそのまま使用しても問題ありません。何か他に質問がありましたら、お気軽にお申し付けください。
最後の修正となりました!!flatMapを初めて目にしたので、この修正であっているか自信がないです。
修正前:
export async function getAllTags(): Promise<SelectProperty[]> {
const allPosts = await getAllPosts()
const tagNames: string[] = []
return allPosts
.flatMap((post) => post.Tags)
.reduce((acc, tag) => {
if (!tagNames.includes(tag.name)) {
acc.push(tag)
tagNames.push(tag.name)
}
return acc
}, [] as SelectProperty[])
.sort((a: SelectProperty, b: SelectProperty) =>
a.name.localeCompare(b.name)
)
}
修正後:
export async function getAllTags(): Promise<SelectProperty[]> {
const allPosts = await getAllPosts()
const tagNames: string[] = []
return allPosts
.filter(
(post) => !!post.Rank && !post.Tags.some((tag) => tag.name === 'footer')
)
.flatMap((post) => post.Tags)
.reduce((acc, tag) => {
if (!tagNames.includes(tag.name)) {
acc.push(tag)
tagNames.push(tag.name)
}
return acc
}, [] as SelectProperty[])
.sort((a: SelectProperty, b: SelectProperty) =>
a.name.localeCompare(b.name)
)
}あなたが提供した修正は、全体としては正確ですが、一部注意すべき点があります。
あなたの修正コードでは、まずすべての投稿を取得し、それから特定の投稿をフィルタリングしています。そのフィルタリングの条件は、「投稿がランクを持っている(!!post.Rank)」と「投稿が'footer'タグを持っていない(!post.Tags.some((tag) => tag.name === 'footer'))」の両方を満たすものです。
ただし、ここで注意すべきなのは、!!post.Rankという部分です。これはその投稿がランクを持っているかどうかを判定しますが、元々の関数の目的は「すべてのタグを取得する」ことです。つまり、ランクを持っているかどうかはこの関数の目的とは関係がありません。したがって、これが意図したものでなければ、!!post.Rankという条件は削除するべきです。
修正後のコードは以下のようになります:
export async function getAllTags(): Promise<SelectProperty[]> {
const allPosts = await getAllPosts()
const tagNames: string[] = []
return allPosts
.filter((post) => !post.Tags.some((tag) => tag.name === 'footer'))
.flatMap((post) => post.Tags)
.reduce((acc, tag) => {
if (!tagNames.includes(tag.name)) {
acc.push(tag)
tagNames.push(tag.name)
}
return acc
}, [] as SelectProperty[])
.sort((a: SelectProperty, b: SelectProperty) =>
a.name.localeCompare(b.name)
)
}この修正により、'footer'タグを持つ投稿が全てのタグを取得する処理から除外されます。もしこれがあなたの求める動作であれば、この修正をそのまま使っても問題ありません。
すみません。参考にしたコードをそのままコピペしてしまい、余計な部分がついてましたね。以後気をつけます
全く問題ありません!修正すべき部分を見つけ出すのは、コードを学ぶ上で非常に重要なスキルです。そして、それはあなたが成功裏に行ったことです。コードについて理解を深め、それを修正し、それを他人と共有することは、非常に重要なステップです。何か他の質問がありましたら、お気軽にお申し付けください。
ありがとう\(^o^)/\(^o^)/

記事ページのコード
export async function getStaticPaths() {
const posts = await getAllPosts()
return posts.map((post: interfaces.Post) => ({ params: { slug: post.Slug } }))
}
const { slug } = Astro.params
const post = await getPostBySlug(slug)
if (!post) {
throw new Error('Post not found. slug: ${slug}')
}
const [blocks, allPosts, rankedPosts, recentPosts, tags, postsHavingSameTag] =
await Promise.all([
getAllBlocksByBlockId(post.PageId),
getAllPosts(),
getRankedPosts(),
getPosts(5),
getAllTags(),
getPostsByTag(post.Tags[0]?.name, 6),
])
const fileAtacchedBlocks = extractTargetBlocks('image', blocks)
.concat(extractTargetBlocks('file', blocks))
.filter((block) => {
if (!block) {
return false
}
const imageOrFile = block.Image || block.File
return imageOrFile && imageOrFile.File && imageOrFile.File.Url
})
// Download files
await Promise.all(
fileAtacchedBlocks
.map(async (block) => {
const expiryTime = (block.Image || block.File).File.ExpiryTime
if (Date.parse(expiryTime) > Date.now()) {
return Promise.resolve(block)
}
return getBlock(block.Id)
})
.map((promise) =>
promise.then((block) => {
let url!: URL
try {
url = new URL((block.Image || block.File).File.Url)
} catch (err) {
console.log('Invalid file URL')
return Promise.reject()
}
return Promise.resolve(url)
})
)
.map((promise) => promise.then(downloadFile))
)
const currentPostIndex = allPosts.findIndex((post) => post.Slug === slug)
const prevPost = allPosts[currentPostIndex + 1]
const nextPost = allPosts[currentPostIndex - 1]
let ogImage = ''
if (post.FeaturedImage && post.FeaturedImage.Url) {
ogImage = new URL(filePath(new URL(post.FeaturedImage.Url)), Astro.site)
}そもそもの原因が、直接getAllPostsからデータを取得していることによるもの👀
さて、どこにfilterをかけようか….
Promptが長いのでトグルに収納してお届けしますww
保守性を意識して定義する関数の部分でfilterを加えました。パフォーマンスやわかりやすさも加味して評価いただけると嬉しいです
修正前:
```export async function getStaticPaths() { const posts = await getAllPosts() return posts.map((post: interfaces.Post) => ({ params: { slug: post.Slug } }))}const { slug } = Astro.paramsconst post = await getPostBySlug(slug)if (!post) { throw new Error('Post not found. slug: ${slug}')}const [blocks, allPosts, rankedPosts, recentPosts, tags, postsHavingSameTag] = await Promise.all([ getAllBlocksByBlockId(post.PageId), getAllPosts(), getRankedPosts(), getPosts(5), getAllTags(), getPostsByTag(post.Tags[0]?.name, 6), ])const fileAtacchedBlocks = extractTargetBlocks('image', blocks) .concat(extractTargetBlocks('file', blocks)) .filter((block) => { if (!block) { return false } const imageOrFile = block.Image || block.File return imageOrFile && imageOrFile.File && imageOrFile.File.Url })// Download filesawait Promise.all( fileAtacchedBlocks .map(async (block) => { const expiryTime = (block.Image || block.File).File.ExpiryTime if (Date.parse(expiryTime) > Date.now()) { return Promise.resolve(block) } return getBlock(block.Id) }) .map((promise) => promise.then((block) => { let url!: URL try { url = new URL((block.Image || block.File).File.Url) } catch (err) { console.log('Invalid file URL') return Promise.reject() } return Promise.resolve(url) }) ) .map((promise) => promise.then(downloadFile)))const currentPostIndex = allPosts.findIndex((post) => post.Slug === slug)const prevPost = allPosts[currentPostIndex + 1]const nextPost = allPosts[currentPostIndex - 1]let ogImage = ''if (post.FeaturedImage && post.FeaturedImage.Url) { ogImage = new URL(filePath(new URL(post.FeaturedImage.Url)), Astro.site)}```
修正後:
```export async function getStaticPaths() { const posts = await getAllPosts() return posts.map((post: interfaces.Post) => ({ params: { slug: post.Slug } }))}const { slug } = Astro.paramsconst post = await getPostBySlug(slug)if (!post) { throw new Error('Post not found. slug: ${slug}')}const [blocks, allPosts, rankedPosts, recentPosts, tags, postsHavingSameTag] = await Promise.all([ getAllBlocksByBlockId(post.PageId), getAllPosts().filter( (post) => !post.Tags.some((tag) => tag.name === 'footer') ), getRankedPosts(), getPosts(5), getAllTags(), getPostsByTag(post.Tags[0]?.name, 6), ])const fileAtacchedBlocks = extractTargetBlocks('image', blocks) .concat(extractTargetBlocks('file', blocks)) .filter((block) => { if (!block) { return false } const imageOrFile = block.Image || block.File return imageOrFile && imageOrFile.File && imageOrFile.File.Url })// Download filesawait Promise.all( fileAtacchedBlocks .map(async (block) => { const expiryTime = (block.Image || block.File).File.ExpiryTime
if (Date.parse(expiryTime) > Date.now()) { return Promise.resolve(block) } return getBlock(block.Id) }) .map((promise) => promise.then((block) => { let url!: URL try { url = new URL((block.Image || block.File).File.Url) } catch (err) { console.log('Invalid file URL') return Promise.reject() } return Promise.resolve(url) }) ) .map((promise) => promise.then(downloadFile)))const currentPostIndex = allPosts.findIndex((post) => post.Slug === slug)const prevPost = allPosts[currentPostIndex + 1]const nextPost = allPosts[currentPostIndex - 1]let ogImage = ''if (post.FeaturedImage && post.FeaturedImage.Url) { ogImage = new URL(filePath(new URL(post.FeaturedImage.Url)), Astro.site)}```
ご指摘いただいたコードを見たところ、修正点についてはおおむね正しく反映されているように思います。ただし、修正後のコードで注意すべき点が一つあります。
修正後のコードで、getAllPosts()関数がPromiseを返す非同期関数であることを考慮して、filter()を使用する前に非同期処理が終わるのを待つ必要があります。そのため、修正後のコードの該当箇所は以下のようになるべきです:
const allPostsFiltered = (await getAllPosts()).filter((post) => !post.Tags.some((tag) => tag.name === 'footer'));あるいは以下のように非同期処理を待つ部分を明示的に分けて書くこともできます:
const allPosts = await getAllPosts();
const allPostsFiltered = allPosts.filter((post) => !post.Tags.some((tag) => tag.name === 'footer'));また、その修正によりallPostsFilteredを参照する他の部分(例えばconst currentPostIndex = allPosts.findIndex((post) => post.Slug === slug), const prevPost = allPosts[currentPostIndex + 1], const nextPost = allPosts[currentPostIndex - 1]など)もallPostsではなくallPostsFilteredを使用するように修正する必要があります。
本家の関数名はなるべく残したいのでallPostsを使って修正したいです
その場合、以下のようにallPostsを再定義して、それを使用するという方法があります:
let allPosts = await getAllPosts()
allPosts = allPosts.filter((post) => !post.Tags.some((tag) => tag.name === 'footer'))このようにすれば、関数内のその後のallPostsの参照すべてがフィルタリングされた結果を指すようになります。ただし、変数allPostsが再代入可能である(letで定義されている)ことを確認してください。constで定義されている場合、再代入は不可能です。
このように修正してみました。
const [
blocks,
allPostsNoFinter,
rankedPosts,
recentPosts,
tags,
postsHavingSameTag,
] = await Promise.all([
getAllBlocksByBlockId(post.PageId),
getAllPosts(),
getRankedPosts(),
getPosts(5),
getAllTags(),
getPostsByTag(post.Tags[0]?.name, 6),
])
const allPosts = allPostsNoFinter.filter(
(post) => !post.Tags.some((tag) => tag.name === 'footer')
)
その修正は適切です。allPostsNoFilterという新しい変数名を導入することで、コードの意味がより明確になりました。これにより、他の開発者(あるいは将来のあなた自身)がコードを読むときに、その変数がフィルタリングされていない全てのポストを含んでいるということを理解しやすくなります。
また、allPostsの再定義も適切で、この変数が以前と同じ目的(すなわち、全てのポストを含むが今回は'footer'タグのポストを除いている)に用いられることが分かります。
この修正により、コードの可読性と保守性が向上したと言えます。
安易に関数名を変えると、
本家からのアップデート作業で苦労するのが目に見えていたので
なるべく内側を変更することにしました🎉
今回のコードはこちら!!