1
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?

useAsync の使い方を学んでみた

Last updated at Posted at 2024-12-27

useAsync とは

useAsyncは、react-useというReact アプリケーションでよく使われる機能を簡単に実装するための便利なフックライブラリの中のひとつです。

GitHub > react-use

useAsync のドキュメントを読んでみる

GitHub > react-use > useAsync

useAsync は、非同期関数(またはプロミスを返す関数)を解決する React フック です。

Reference

  useAsync(fn, args?: any[]);
  • fn: 非同期関数。非同期処理を実行し、結果を返す。
  • args?: 依存配列。この配列に指定した値が変わると、useAsync内の非同期関数が再度呼び出される。依存配列が空の場合は、最初のレンダリング時にのみ実行される。

Usage

import {useAsync} from 'react-use';

const Demo = ({url}) => {

  // useAsync を使って非同期関数を呼び出す
  const state = useAsync(async () => {
    const response = await fetch(url);   // URL からデータを取得する
    const result = await response.text();   // レスポンスをテキストとして取得する

    return result   // 取得した結果を返す
  }, [url]);   // URL が変わる度に非同期関数が再実行される

  return (
    <div>
      {state.loading
        ? <div>Loading...</div>   // 読込中は「Loading...」を表示する
        : state.error
          ? <div>Error: {state.error.message}</div>   // エラーが発生した場合は、エラーメッセージを表示する
          : <div>Value: {state.value}</div>   // 成功した場合は取得したデータを表示する
      }
    </div>
  );
};
  • useAsync は、非同期関数の戻り値を返す
  • useAsync の戻り値は、オブジェクト
  • useAsync は戻り値に対して、loadingerrorvalueの3つのステートを管理している

へ〜。エラーハンドリングもしやすくて、なんかよさそうな感じがする!!!

refactor: サンプルコードの三項演算子をやめてみる

三項演算子をやめて早期リターンしてしまう書き方もよいのでは?ということで、リファクタリングしつつ、jsx から tsx に書き換えてみる。

import { useAsync } from 'react-use';

interface DemoProps {
  url: string;
}

const Demo = ({ url }: DemoProps) => {
  const state = useAsync(async () => {
    const response = await fetch(url);

    return await response.text();
  }, [ url ]);

  if (state.loading) return <div>Loading...</div>
  if (state.error) return <div>Error: { state.error.message }</div>

  return (
    <div>Value: { state.value }</div>
  );
};

export default Demo;

うん、なんかスッキリしてきた。

state.value だけ使えればいいんだけどな・・・

と、思うこともあるかもしれない。
分割代入でいけるのか・・・?

import { useAsync } from 'react-use';

interface DemoProps {
  url: string;
}

const Demo = ({ url }: DemoProps) => {
  const { value: state } = useAsync(async () => {
    const response = await fetch(url);
    
    return await response.text();
  }, [ url ]);

  return (
    <div>Value: { state }</div>
  );
};

export default Demo;

value の値を state という名前で取り出すこと(エイリアス)ができた☆
分割代入からのエイリアス。なんかオシャレ♫

state の値が配列だったらどうなる?

リポジトリから todo のリストが配列で返ってくることを想定して書いてみた。

import { useAsync } from 'react-use';
import { TodoListRepository } from "@/repository/todoRepository.ts";

export const Demo = ({ todoRepository }: { todoRepository:TodoListRepository }) => {
  const { value: todoList } = useAsync(async () => {
    return await todoRepository.getList();
  }, [todoRepository]);

  return (
    <>
      {todoList?.map((todo) => (
        <div key={todo.id}>{ todo.id }: {todo.title}</div>
      ))}
    </>
  );
};

うん、いいかも。
useAsyncvalue の戻り値の型は、TodoList[] | undefind みたいな形になっていて undefind が入ってくる可能性があるので、オプショナルチェイニング演算子 ( ?. ) を使って回避したり、todoList[] || [] みたいな形で todoListundefind が入ってきたら空の配列を返すようにするなどの工夫が必要かなと思います。

おわりに

useAsyncが何者かわからず、もやもやしたまま使っていたので、スッキリしました!!
react-useには他にも色々フックが用意されているみたいなので、うまく活用できるといいな〜。

1
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
1
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?