💼

edamam apiでRecipe web pageを作る

2024/04/18に公開

現在、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つの主要な状態であるisLoadingisErrordataを通じて、コンポーネントでデータのローディング状態やエラー、実際のデータを簡単に扱うことができます。

edamam api

https://developer.edamam.com/admin/applications
Edamam APIには3種類のAPIがあり、それぞれのAPIのIDとキーを取得する必要があります。私が受けた課題は、Recipe Search APIを使用して検索機能を作ることだったので、Recipe Search APIのみを使用すれば良いです!


APIの使用方法はこちらで確認できます。
https://developer.edamam.com/edamam-docs-recipe-api

SearchPage

useSearchParams()を使用すると、クエリストリングのパラメータにアクセスできます。また、useQuery()isLoadingisErrorerrorを簡単に管理できるようにします。

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