APIレスポンスの扱いが正直怪しい人集合!!

APIレスポンスの扱いが正直怪しい人集合!!

投稿日: 2024年12月04日

学習振り返り
要約
  • 非同期処理の基本を解説し、APIリクエストの際のデータ取得方法について説明します。
  • useStateフックを使ったステート管理とuseEffectフックで初回レンダリング時の処理を実行する方法を示します。
  • 分割代入の仕組みや、エラーハンドリングの重要性についても触れ、理解を深めるためのポイントをまとめました。

はじめに

JS最初の山であろう非同期処理ですが、あのあたりの処理がいつも決まった書き方してるけどよくわからずに書いているんだよね実はっていう方に向けて解説します~!

分割代入にも少し触れます!

よくあるAPIリクエストとその後の処理

こんな処理よくやりますよね??

const [data, setData] = useState<Post[]>();
const [isLoading, setLoading] = useState(true);
useEffect(() => {
    const fetcher = async () => {
      const resp = await fetch("/api/posts/", { method: "GET" });
      const { posts }: { posts: Post[] } = await resp.json();
      setData(posts);
      setLoading(false);
    };
    fetcher();
  }, []);

ここイマイチ理解していないよって方に向けてます!

エラーハンドリング(try-catch)省略していますが、実際はすべきです!
APIリクエストは失敗する可能性があるので、エラーが発生した時に処理が止まってしまわないようにエラーはキャッチするようにする必要があります。

念のため、Postの定義はこちらです。

export interface Post {
  id: number;
  title: string;
  thumbnailImageKey: string;
  createdAt: Date;
  updatedAt: Date;
  content: string;
  postCategories: PostCategory[];
}

export interface PostCategory {
  id: number;
  postId: number;
  categoryId: number;
  createdAt: Date;
  updatedAt: Date;
  post: Post;
  category: Category;
}

export interface Category {
  id: number;
  name: String;
  createdAt: Date;
  updatedAt: Date;
  posts: PostCategory[];
}

解説

ステートを定義

const [data, setData] = useState<Post[]>(); 
const [isLoading, setLoading] = useState(true);

取得したデータを管理するためのdata、読込み状況の管理のためのisLoadingです。

dataはPost[]、isLoadingはbooleanです。

次にuseEffectです。

下記の記事で解説している初回レンダリング時だけ処理実行のパターンです。


fetcher関数

const fetcher = async () => {
      const resp = await fetch("/api/posts/", { method: "GET" });
      const { posts }: { posts: Post[] } = await resp.json();
      setData(posts);
      setLoading(false);
};

一行ずつ見ていきます。

エンドポイント/api/posts/にGETリクエストを行います。fetchは非同期処理なのでawaitが前につきます。

const resp = await fetch("/api/posts/", { method: "GET" });

awaitを使用する関数はasyncを付けないといけないです!

GETリクエストの場合、メソッドは省略が可能です。下記でもOK!
const resp = await fetch("/api/posts/");

次に、データを変換します。

const { posts }: { posts: Post[] } = await resp.json();

レスポンスが入っているrespResponse オブジェクトで、その中のボディはストリーム形式です。

そのままでは必要なデータを扱えないという問題があります。そこで、resp.json()を行うことでjson形式のデータをJSで操作可能なオブジェクトに変換してオブジェクトとして扱えるようにします。

ザックリ、文字列みたいになってて、ほしいデータにアクセスできる状態じゃないからオブジェクトに変換するみたいなイメージで良いと思います・・!

これも非同期処理なのでawaitが付きます。

ストリームとは
データを順序立てて連続的に送受信する手法のことです。これにより大量のデータを効率的に扱うことができるみたいです。(知らんやったので調べました笑)

型を指定しないでanyのままでもいいとは思いますが、この後Posts型のステートに値をセットするので、型は一致させておいた方がいいのではと個人的には思います。

分割代入

ちなみにあれ??ってなってる方を結構お見かけしますのであえてお伝えしますと、分割代入しています。

分割代入をしない場合の書き方例は下記のような感じです。

const data = await resp.json();
const posts = data.posts;

{posts:[…]}このようなオブジェクトからpostsを直接代入しているというかんじです。

分割代入は波カッコ{}で囲ってオブジェクトのプロパティ名を直接指定しすることで直接プロパティの値を代入する記法です。よく使うので押さえておきたいところです!

ステートの値を更新

setData(posts);
setLoading(false);

更新関数を使ってステートに値を定義します。

postsの型がPosts[]で、ステートdataもPosts[]なので型一致しててちゃんと入ります〇

isLoadingもfalseに更新することで

if (isLoading) return <div>読み込み中...</div>;

ここでリターンされずに次の処理にすすみます。

最後に

 fetcher();

で関数実行することで、初回レンダリング時にのみデータ取得することが出来ます!

おわりに

初心者向けな内容でしたが、なんとなくサンプルコードコピペしてるから理解が怪しいと実は思ってる方の確認に使えたらいいなと思います🎵

シェア!

Threads
user
吉本茜
山口在住/二児の母/育休中
Loading...
記事一覧に戻る
Threads
0