0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React】AbortController

Posted at

はじめに

こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。

フロントエンド開発では API リクエストを投げた後に 「もう結果が不要になった」 ということがよくあります。

  • 検索フォームで入力するたびにリクエストする場合、古いリクエストは無駄になる
  • React コンポーネントがアンマウントされたあとにリクエストが残っていると、メモリリークや警告の原因になる

こうした「不要になったリクエスト」を止められる仕組みが AbortController です。
この記事では、AbortController の基本から、実際の使いどころまでを整理します。


基本の使い方

import axios from 'axios';

async function fetchData() {
  const controller = new AbortController();

  try {
    const res = await axios.get('/api/data', { signal: controller.signal });
    console.log(res.data);
  } catch (err) {
    if (axios.isCancel(err)) {
      console.log('リクエストがキャンセルされました');
    } else {
      console.error('通信エラー:', err);
    }
  }

  // 必要なくなったら中断
  controller.abort();
}

fetchData();

ポイント:

  • axios のオプションに signal を渡す
  • controller.abort() を呼ぶと AxiosError が投げられる
  • axios.isCancel(err) でキャンセルかどうかを判定できる

React での使いどころ

1. useEffect のクリーンアップ

コンポーネントが消えるときにリクエストをキャンセル。

import { useEffect, useState } from 'react';
import axios from 'axios';

export const UserList = () => {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    const controller = new AbortController();

    const fetchUsers = async () => {
      try {
        const res = await axios.get('/api/users', {
          signal: controller.signal,
        });
        setUsers(res.data);
      } catch (err) {
        if (!axios.isCancel(err)) {
          console.error('ユーザー取得に失敗:', err);
        }
      }
    };

    fetchUsers();

    return () => {
      controller.abort(); // クリーンアップ時にキャンセル
    };
  }, []);

  return (
    <ul>
      {users.map((u) => (
        <li key={u.id}>{u.name}</li>
      ))}
    </ul>
  );
};

2. 入力中の古いリクエストを破棄する

検索フォームなどでは「新しいキーワード入力時に古いリクエストをキャンセル」すると UX が良くなる。

import { useEffect, useState } from 'react';
import axios from 'axios';

export const SearchBox = ({ keyword }: { keyword: string }) => {
  const [result, setResult] = useState([]);

  useEffect(() => {
    const controller = new AbortController();

    const fetchSearch = async () => {
      try {
        const res = await axios.get(`/api/search?q=${keyword}`, {
          signal: controller.signal,
        });
        setResult(res.data);
      } catch (err) {
        if (!axios.isCancel(err)) {
          console.error('検索失敗:', err);
        }
      }
    };

    fetchSearch();

    return () => {
      controller.abort(); // 新しい検索時に前のリクエストをキャンセル
    };
  }, [keyword]);

  return <div>{JSON.stringify(result)}</div>;
};

まとめ

  • AbortController は リクエストを途中で止める仕組み
  • axios では signal を渡し、不要になったら abort()
  • React では useEffect のクリーンアップや検索フォームに特に有効
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?