React Hook Formを使ってインクリメンタルサーチを実装するサンプルコードを以下に示します。インクリメンタルサーチでは、ユーザーが入力するたびにAPIリクエストを送信し、検索結果を表示します。
### FastAPI エンドポイントのコード(サンプルデータ付き)
```python
from fastapi import FastAPI, Query
from urllib.parse import unquote
app = FastAPI()
# サンプルデータ
sample_data = {
"apple": "A fruit",
"banana": "Another fruit",
"carrot": "A vegetable"
}
@app.get("/search")
async def search_endpoint(
searchword: str = Query(..., description="検索キーワード")
):
decoded_searchword = unquote(searchword) # URLエンコードされたsearchwordをデコード
results = {key: value for key, value in sample_data.items() if decoded_searchword.lower() in key.lower()}
return results
```
### React Hook Form とインクリメンタルサーチのコード
```jsx
import React, { useState } from 'react';
import { useForm } from 'react-hook-form';
const IncrementalSearch = () => {
const { register, handleSubmit, watch } = useForm();
const [results, setResults] = useState();
const searchword = watch("searchword");
const fetchResults = async (searchword) => {
if (searchword.trim() === "") {
setResults();
return;
}
const encodedSearchword = encodeURIComponent(searchword);
const url = `http://localhost:8000/search?searchword=${encodedSearchword}`;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
setResults(data);
} catch (error) {
console.error('Error fetching data:', error);
}
};
// React Hook Formのwatchで検索ワードの変化を監視
React.useEffect*1}
</ul>
</div>
);
};
export default IncrementalSearch;
```
### 説明
1. **FastAPIエンドポイント**:
- `/search` エンドポイントは、`searchword` クエリパラメータを受け取り、サンプルデータの中から検索ワードを含むエントリを返します。
2. **React Hook Formのセットアップ**:
- `useForm` フックを使ってフォームを管理します。
- `watch` を使って検索ワードの変化を監視します。
3. **インクリメンタルサーチの実装**:
- `useEffect` フックを使って、`searchword` の変化を監視し、入力が変わるたびにAPIリクエストを送信します。
- 300ミリ秒のディレイを設けて、ユーザーが入力するたびにすぐにAPIリクエストを送信しないようにし、パフォーマンスを最適化しています。
4. **結果の表示**:
- 取得した結果をリストとして表示します。
このコードを使用することで、ユーザーが入力するたびにリアルタイムで検索結果を取得し、表示するインクリメンタルサーチが実現できます。
*1:) => {
const timer = setTimeout(() => {
fetchResults(searchword);
}, 300); // 300msのディレイを設けてAPI呼び出しを最適化
return () => clearTimeout(timer);
}, [searchword]);
return (
<div>
<form>
<input
type="text"
placeholder="検索キーワード"
{...register("searchword")}
/>
</form>
<ul>
{Object.entries(results).map(([key, value]) => (
<li key={key}>
<strong>{key}:</strong> {value}
</li>