// フィルタリング機能付きのブログ一覧
function FilterableBlogCards({blogs}) {
return (
<div>
<BlogSearchBar searchName={""} />
{blogs.map((blog) => {
return <BlogCard blog={blog} key={blog.id} />
})}
</div>
)
}
function BlogSearchBar({searchName}) {
return (
<div className="flex justify-center">
<input
className="長いので省略..."
value={searchName}
placeholder="キーワードを入力..."
/>
</div>
)
}
function BlogCard({blog}) {
return (
<Card
className="m-2 flex flex-col justify-center sm:w-1/3 md:w-1/5"
key={blog.year + blog.month + blog.date + blog.title}
>
<CardLink to={""}>
<CardImage type={cardType} />
<CardContent title={blog.title} year={blog.year} month={blog.month} date={blog.date} />
</CardLink>
</Card>
)
}
// 以下のコンポーネントは省略
function Card() {
return ...
}
function CardLink() {
return ...
}
function CardImage() {
return ...
}
function CardContent() {
return ...
}
// フィルタリング機能付きのブログ一覧
function FilterableBlogCards({blogs}) {
const [searchName, setSearchName] = useState('')
const [filteredBlogs, setFilteredBlogs] = useState(blogs)
// filteredBlogsとsearchNameを表示または子コンポーネントに渡す
return ...
}
現在のデータフロー
// フィルタリング機能付きのブログ一覧
function FilterableBlogCards({blogs}) {
const [searchName, setSearchName] = useState('')
// イベントハンドラを定義
const handleHangeSearchName = (e: ChangeEvent<HTMLInputElement>) => {
setSearchName(e.target.value)
}
// ブログのフィルタリング処理
...
return (
<div>
{/* 定義したイベントハンドラを渡す */}
<BlogSearchBar searchName={searchName} onChange={handleHangeSearchName} />
...
)
}
いかがだったでしょうか? Reactの流儀の5つのステップを行ったことでReactにおける開発のメンタルモデルが少しでも形成されていたら嬉しいです。 最終的なコードを載せます。 一部、ステップには載せなかった記述もあります。 必要に応じて確認してください。
// フィルタリング機能付きのブログ一覧
function FilterableBlogCards({blogs}) {
const [searchName, setSearchName] = useState('')
const [filteredBlogs, setFilteredBlogs] = useState(blogs)
const handleHangeSearchName = (e: ChangeEvent<HTMLInputElement>) => {
setSearchName(e.target.value)
filterBlogs(e.target.value)
}
// 今回紹介していないコードです。
const filterBlogs = (searchNameValue: string) => {
const results = BlogTitles.filter((blog) => blog.title.includes(searchNameValue))
setFilteredBlogs(results)
}
return (
<div>
<BlogSearchBar searchName={searchName} onChange={handleHangeSearchName} />
{filteredBlogs.map((blog) => {
return <BlogCard blog={blog} key={blog.id} />
})}
</div>
)
}
function BlogSearchBar({searchName,onChange}) {
return (
<div className="flex justify-center">
<input
className="長いので省略..."
value={searchName}
placeholder="キーワードを入力..."
onChange={onChange}
/>
</div>
)
}
function BlogCard({blog}) {
return (
<Card
className="m-2 flex flex-col justify-center sm:w-1/3 md:w-1/5"
key={blog.year + blog.month + blog.date + blog.title}
>
<CardLink to={""}>
<CardImage type={cardType} />
<CardContent title={blog.title} year={blog.year} month={blog.month} date={blog.date} />
</CardLink>
</Card>
)
}
// 以下のコンポーネントは省略
function Card() {
return ...
}
function CardLink() {
return ...
}
function CardImage() {
return ...
}
function CardContent() {
return ...
}