edamam apiでRecipe web pageを作る
現在、Reactの勉強会グループプロジェクトに参加しています。フロントエンドのみで行うプロジェクトだったため、APIは別に取得しました。
ディレクトリ構成
プロジェクトを進める中で感じたことですが、会社で行うプロジェクトのディレクトリ構成とは大きく異なっていました。
それぞれのページ内にコンポーネントを作成し、一つのコンポーネントで管理するよりも、各ページ内でコンポーネントを作成して管理する方が見やすいと思いました。また、utils/api.js
内でaxios
を使用して常に使用するAPI URL
を事前に設定しておくことで、より簡潔なコードになることがわかりました。
import axios from "axios";
export const api_edamam = axios.create({
baseURL: "https://api.edamam.com",
headers: {
Accept: "application/json",
ContentType: "application/json",
EdamamAccountUser: process.env.REACT_APP_EDAMAM_ACCOUNT_USER,
},
});
また、useQueryを使用してデータのフェッチを行います。useQueryは非同期データを取得し、キャッシュし、更新するプロセスを簡単に処理できます。
const fetchRecipesBySearch = async (keyword, sortBy = "relevance") => {
try {
const response = await api_edamam.get(
`/search?q=${keyword}&app_id=${APP_ID}&app_key=${APP_KEY}&sort=${sortBy}`
);
return response.data;
} catch (error) {
console.error("Error fetching recipes:", error);
return null;
}
};
export const useSearchRecipesQuery = ({ keyword }) => {
return useQuery({
queryKey: ["search-recipes", keyword],
queryFn: () => fetchRecipesBySearch(keyword),
enabled: !!keyword,
select: (data) => {
const recipes = data?.hits.map((hit) => {
const recipe = hit.recipe;
return {
...recipe,
id: extractRecipeId(recipe.uri),
calories: recipe.calories,
totalTime: recipe.totalTime,
};
});
},
staleTime: 3000,
keepPreviousData: true,
});
queryKey
はデータを識別するためのユニークキーです。queryFn
は実際のデータをサーバーや他のソースから取得する関数です。select
を使用すると、データの中から必要なデータを取り出すことができます。
useQuery
を使用すると、データリクエストの3つの主要な状態であるisLoading
、isError
、data
を通じて、コンポーネントでデータのローディング状態やエラー、実際のデータを簡単に扱うことができます。
edamam api
APIの使用方法はこちらで確認できます。
SearchPage
useSearchParams()
を使用すると、クエリストリングのパラメータにアクセスできます。また、useQuery()
はisLoading
、isError
、error
を簡単に管理できるようにします。
const SearchRecipe = () => {
const [query] = useSearchParams();
const keyword = query.get("q");
const {
data: recipeList,
isLoading,
isError,
error,
} = useSearchRecipesQuery({
keyword,
});
if (isLoading) {
return <h1>Loading...</h1>;
}
if (isError) {
return <Alert variant="danger">{error.message}</Alert>;
}
console.log(recipeList, "recipeList");
return (
<main className="main inner">
<section className="sec search-recipe">
<h1>
Search Results for:
<span>{keyword}</span>
</h1>
<article className="search-card-box">
<ul className="search-card-ul">
{recipeList &&
recipeList.map((recipe, index) => (
<RecipeList recipe={recipe} key={index} />
))}
</ul>
</article>
</section>
</main>
);
};
export default SearchRecipe;
結論
プロジェクトはまだ終わっていませんが、このプロジェクトを通じてページごとのコンポーネント管理の重要性を認識し、axiosを活用したAPI設定でコードをシンプルに保つ方法を学びました。また、useQueryを通じてデータフェッチングと状態管理をより効率的に行うことができるようになりました。これからのプロジェクトではディレクトリ管理を改善し、useQueryを使用してさらにシンプルなコードを書くことを目指します。
Discussion