1
1

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】データ取得中ローディング画面が表示されない

Posted at

事象

TODOアプリにおいて、supabaseからテストデータを取得させる間にローディング画面が表示されるよう実装したのですが、取得したデータは表示されるもののローディング画面は表示されない、という現象が発生しました。

コード

(App.jsx及びsupabase関係のコンポーネントは省略)

LogContent.jsx

import { useState, useEffect } from 'react';
import { getAllLogs } from '../utils/supabaseFunctions';

export const LogContent = () => {
  const [logs, setLogs] = useState([]);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const getLogs = async () => {
      const logs = await getAllLogs();
      setLogs(logs);
    };
    getLogs();
    setIsLoading(false);
  }, []);


  return isLoading ? (
    <div>Loading...</div>
  ) : (
    <div>
      <h2>学習記録一覧</h2>
      {logs.map((log) => (
        <p key={log.id}>
          {log.title} {log.time}時間
        </p>
      ))}
    </div>
  );
};

原因

useEffect内での非同期処理の扱いをよく理解しておらず、setIsLoading(false)が不適切なタイミングで実行されてしまうことが原因でした。

getLogs()async関数ですが、この関数は非同期処理getAllLogs()が呼び出されると、結果が帰ってくるまで制御をasyncの呼び出し元の関数に返します。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/async_function

この場合の呼び出し元はuseEffectですから、await getAllLogs()が完了するのを待つことなく次の行のsetIsLoading(false)が実行されてしまうことになります。

useEffect(() => {
    const getLogs = async () => {
        const logs = await getAllLogs();
        setLogs(logs);
    };
    getLogs(); //処理を開始
    // await getAllLogs()の結果が返ってくるまで制御がuseEffectに戻る
    setIsLoading(false); // 非同期処理の完了を待たずに実行
}, []);

ある処理を実行している間に他の処理を並行して実行するのが非同期処理ですから、これは当然の流れなのですが、非同期処理への理解が浅かったためすぐには原因がわからず、だいぶ悩みました。

対処

try...catch...finallyを使用し、setIsLoading(false)の実行タイミングを制御することで解決しました。

useEffect(() => {
    const getLogs = async () => {
        try {
            setIsLoading(true); // データ取得開始前にtrueに設定
            const fetchedLogs = await getAllLogs();
            setLogs(fetchedLogs);
        } catch (error) {
            console.error("読込エラーです:", error);
        } finally {
            setIsLoading(false); // データ取得完了後にfalseに設定
        }
    };

    getLogs();
}, []);

JISOUのメンバー募集中!

プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてください!
▼▼▼

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?