2
2

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 / TypeScript】no-unsafe-finally エラーの原因と解決方法

Posted at

はじめに

React + TypeScript でアプリを作っているときに、ESLint の no-unsafe-finally エラーが出ました。

問題

非同期処理( try ... finally )の中に finally ブロックを使ってローディング状態をリセットするコードを書いていたところ、以下のような ESLint エラーが出ました。

Unsafe usage of ReturnStatementno-unsafe-finally

該当コードはこんな感じ

useEffect(() => {
  let cancelled = false;

  const load = async () => {
    setLoading(true);
    try {
      const response = await fetchDashboard();
      if (cancelled) return;
      setData(response);
    } catch (err) {
      if (cancelled) return;
      setError((err as Error).message ?? "ダッシュボードの読み込みに失敗しました");
    } finally {
      if (cancelled) return;  // ← ここでエラー
      setLoading(false);
    }
  };

  load();

  return () => {
    cancelled = true;
  };
}, [user]);

解決方法

どうやら、try ... finally ブロックの中では return / throw / break / continue を使ってはいけないようでした。

finally の中で return をすると、try-catch の結果を上書きしてしまい、意図しない制御フローになるそうです。

代わりに、単純な if で制御しました。

finally {
  if (!cancelled) {
    setLoading(false);
  }
}

なぜこんな書き方をしたのか

正直、「try と catch の中で if (cancelled) return を書いているから、finally にも同じように書いとけばいいや」という安直な考えでした(*´-`)

おわりに

finally は「どんな場合でも最後に実行される」という性質があるので、return を書いてしまうと予期しない挙動になりやすいです。
今回のような useEffect 内のクリーンアップ処理では、return せずにガードで分岐させるのが良さそうです。

参考

2
2
2

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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?