import { searchArticles } from '@/lib/search' import { Seo } from '@/components/ui/seo' import { ArticleCard } from '@/components/article/article-card' import { Link, useSearchParams } from 'react-router-dom' import { getAllArticles, getArticlesByTag, getSearchableArticles } from '@/lib/content' import { useLang, usePrefix, useT } from '@/lib/i18n' export const ArticleListPage = () => { const lang = useLang() const prefix = usePrefix() const t = useT() const [params, setParams] = useSearchParams() const tag = params.get('tag') const query = params.get('q') ?? '' const searching = params.has('q') const candidates = tag ? getArticlesByTag(tag, lang) : searching ? getSearchableArticles(lang) : getAllArticles(lang) const articles = searchArticles(candidates, query) return (

{t.articleListTitle}

{ event.preventDefault() const data = new FormData(event.currentTarget) const next = new URLSearchParams(params) next.set('q', String(data.get('q') ?? '').trim()) setParams(next) }}>

タイトル・説明・シリーズ名・タグを検索します。スペースで区切るとすべての語を含む教材に絞ります。空欄で検索すると全教材を表示します。{tag && '現在のタグ内を検索しています。'}

{searching &&

{query ? `「${query}」の検索結果` : '全教材'}:{articles.length}件 検索とタグを解除

}
{!tag && !searching &&

まず、症状を切り分ける

  • データを読む前に画面が落ちる → undefinedと取得状態
  • 更新や通信が止まらない → Effectの循環
  • 並べ替えたら入力が別の行へ移った → keyの実験
  • 検索結果が前の内容へ戻る → 通信の競合

エラー全文を残し、再現する最小の操作を決めます。修正後も同じ操作で結果を確認してください。

} {tag &&

「{tag}」の記事:{articles.length}件 絞り込みを解除

} {articles.length === 0 ? (

一致する教材はありません。検索語を短くするか、スペースで区切った語を減らしてください。

) : (
{articles.map((article) => ( ))}
)}
) }