8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Reactで非同期処理が可能な副作用フックを作成する

Last updated at Posted at 2019-10-17

1. 背景

Reactの比較的新しい機能であるフック(hooks)を用いると、以下のように関数コンポーネント(function component)の内部で副作用を扱うことが可能になる。

useEffectの例
const Hello = () => {
  useEffect(() => {
    console.log("hello, effect!");
  });

  return <div>Hello, World!</div>
};

この内部でawaitをしたいとしよう(例えば、外部のAPIからデータを取得したい場合など)。
awaitを実行する関数はasyncでなければならないので、単純に以下のように修正してみると、Warningが表示されてしまう。

うまくいかない例
const Hello = () => {
  useEffect(async () => {
    const data = await fetch("http://qiita.com/");
  });

  return <div>Hello, World!</div>
};

2. 解決策

useEffect()に非同期関数を渡すのではなく、useEffect()に渡される関数の中で非同期関数を定義し、呼び出すようにすれば良い。

const Hello = () => {
  useEffect(() => {
    const asyncFunc = async () => {
      const data = await fetch("http://qiita.com/");
    };
    asyncFunc();
  });
  return <div>Hello, World!</div>
};

解決策に対応するカスタムフックの作成

さらに、以下のようなカスタムフックuseAsyncEffect()を作成することで上記解決策のロジックを抽出できる。

カスタムフックuseAsyncEffec()の作成
export function useAsyncEffect(asyncFunc, deps) {
  useEffect(() => {
    (async () => {
      asyncFunc();
    })();
  }, deps)
}

これを用いると、先述の解決策は以下のように簡単に書き換えることができる。

const Hello = () => {
  useAsyncEffect(async () => {
    const data = await fetch("http://qiita.com/");
  });

  return <div>Hello, World!</div>
};

3. 追記:クリーンアップを要する副作用の場合

上記のuseAsyncEffect()ではクリーンアップを有する副作用を上手く扱うことができない。
通常のuseEffect()のようにuseAsyncEffect()内でクリーンアップ関数をreturnできるようにしたかったが、厳しそうなので、ひとまず以下のようにuseAsyncEffect()の引数として渡す形をとることにした。

export function useAsyncEffect(asyncFunc, deps, cleanup=() => {}) {
  useEffect(() => {
    (async () => {
      asyncFunc();
    })();
    return cleanup;
  }, deps);
}

cleanupを渡すときのスコープが変わってしまうため、このままでは上手くいかないケースも考えられる...

8
5
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
8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?