const { useState, useEffect } = React; const { createRoot } = ReactDOM; // 入力からAPIを叩くまでの待ち時間(ミリ秒) const SEARCH_DEBOUNCE_MS = 300; // 議員検索画面。市区町村名・議員名を入力するとリアクティブに検索結果が更新される const GiinSearch = ({ apiBase }) => { const [shichosonName, setShichosonName] = useState(''); const [giinName, setGiinName] = useState(''); const [giins, setGiins] = useState([]); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(''); useEffect(() => { // 市区町村名が空のときは検索しない(APIも空配列を返す) if (!shichosonName.trim()) { setGiins([]); setError(''); setIsLoading(false); return; } // アンマウントや入力変更で古いリクエストの結果を反映させないためのフラグ let isCancelled = false; setIsLoading(true); const timerId = setTimeout(async () => { try { const query = new URLSearchParams({ shichoson_name: shichosonName, name: giinName }); const response = await fetch(`${apiBase}/giins?${query}`); if (isCancelled) return; if (response.ok) { const data = await response.json(); setGiins(data.giins); setError(''); } else { setGiins([]); setError('検索に失敗しました'); } } catch (e) { console.error('Error:', e); if (isCancelled) return; setGiins([]); setError('ネットワークエラーが発生しました'); } finally { if (!isCancelled) setIsLoading(false); } }, SEARCH_DEBOUNCE_MS); return () => { isCancelled = true; clearTimeout(timerId); }; }, [shichosonName, giinName, apiBase]); // 検索結果の表示部分 const renderResults = () => { if (!shichosonName.trim()) { return
議員を検索して、その議員の関心事項を閲覧できます。