実現したいこと
ReactとRecoilを使って、外部サーバーにAPIで記事を取得して、それを画面に表示したいです。
この画面には、検索機能があり、キーワードを入力して「検索」ボタンを押すと、そのキーワードを含む記事が表示されます(キーワードによる絞り込み検索は、API側がやってくれます)
発生している問題・分からないこと
コンポーネントを分けているため、状態をグローバルに管理したいと思い、Recoilを導入しました。
初回画面は、キーワードは空でAPIを呼び出しその結果を<ItemTable>コンポーネント内で表示します。
さらに、<SearchForm>コンポーネント内の入力欄にキーワードを入力し、「検索」ボタンを押すと、そのキーワードをパラメータとして、APIを呼び出し、結果を<ItemTable>コンポーネントに表示します。
分からないことは、「検索」ボタンを押したときにどのような処理を行えば、<ItemTable>コンポーネント内を適切な表示に再レンダリングさせることが出来るかどうかです。
該当のソースコード
App.tsx
1import { RecoilRoot } from "recoil"; 2import { Home } from "./Home"; 3 4function App() { 5 return ( 6 <RecoilRoot> 7 <Home /> 8 </RecoilRoot> 9 ); 10} 11 12export default App; 13
Home.tsx
1import { SearchForm } from "./SearchForm"; 2import { RecoilRoot } from "recoil"; 3import { ItemTable } from "./ItemTable"; 4import { Suspense } from "react"; 5 6export const Home = () => { 7 return ( 8 <RecoilRoot> 9 <h1>記事検索ページ</h1> 10 <SearchForm /> 11 <Suspense fallback={<div>Loading...</div>}> 12 <ItemTable /> 13 </Suspense> 14 </RecoilRoot> 15 ); 16}; 17
SearchForm.tsx
1 2export const SearchForm = () => { 3 return ( 4 <div> 5 <h2>記事を探す</h2> 6 <div className="py-4"> 7 <label>キーワード</label> 8 <input 9 type="text" 10 name="Search" 11 placeholder="キーワード..." 12 /> 13 </div> 14 <div> 15 <button 16 type="button" 17 > 18 検索する 19 </button> 20 </div> 21 </div> 22 ); 23}; 24
ItemTable.tsx
1import { useRecoilValue } from "recoil"; 2import { itemSelector } from "./atom/searchParamAtom"; 3 4export const ItemTable = () => { 5 const items = useRecoilValue(itemSelector); 6 7 return ( 8 <div> 9 <div> 10 <h2>記事一覧</h2> 11 <div> 12 <div> 13 <div>検索結果:{items.length}件</div> 14 <div> 15 <table> 16 <thead> 17 <tr> 18 <th>タイトル</th> 19 <th>作者</th> 20 </tr> 21 </thead> 22 <tbody> 23 {items.map((item) => ( 24 <tr key={item.id}> 25 <td> 26 <p>{item.title}</p> 27 </td> 28 <td> 29 <p>{item.author}</p> 30 </td> 31 </tr> 32 ))} 33 </tbody> 34 </table> 35 </div> 36 </div> 37 </div> 38 </div> 39 </div> 40 ); 41}; 42
searchParamAtom.ts
1import { atom, selector } from "recoil"; 2import axios from "axios"; 3 4interface Item { 5 id: number; 6 title: string; 7 author: string; 8} 9export const keywordAtom = atom({ 10 key: "keywordAtom", 11 default: "", 12}); 13 14 15export const itemSelector = selector<Item[]>({ 16 key: "itemSelector", 17 get: async({ get }) => { 18 const keyword = get(keywordAtom); 19 20 const param = { 21 field_name: keyword, 22 }; 23 const headers = { 24 "Content-Type": "application/json", 25 }; 26 const res = await axios.post("http://localhost:8080/items", param, { 27 headers: headers, 28 }); 29 return res.data; 30 }, 31}); 32
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
初期画面は、全件取得結果が表示されます。検索ボタンを押したときの挙動を実装したいです。
補足
特になし

あなたの回答
tips
プレビュー