React - DOM レンダリング中にローディング画面を表示する 3 つの方法

2024-04-02

React - DOM レンダリング中にローディング画面を表示する

概要

useState フックを使用して、ローディング状態を管理できます。

const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
  // データフェッチなどの非同期処理
  setTimeout(() => {
    setIsLoading(false);
  }, 1000);
}, []);

return (
  <div>
    {isLoading && <LoadingScreen />}
    {!isLoading && <App />}
  </div>
);

Suspense フックを使用して、非同期コンポーネントのレンダリング中にプレースホルダーを表示できます。

const App = () => {
  return (
    <Suspense fallback={<LoadingScreen />}>
      <MyAsyncComponent />
    </Suspense>
  );
};

const MyAsyncComponent = () => {
  // データフェッチなどの非同期処理
  const data = await fetchData();
  return <MyComponent data={data} />;
};

Redux を使用して、ローディング状態をグローバルに管理できます。

const App = () => {
  const { isLoading } = useSelector(state => state.loading);

  return (
    <div>
      {isLoading && <LoadingScreen />}
      {!isLoading && <MyComponent />}
    </div>
  );
};

const mapStateToProps = state => ({
  isLoading: state.loading.isLoading,
});

const mapDispatchToProps = dispatch => ({
  // ローディング開始
  startLoading: () => dispatch({ type: 'START_LOADING' }),
  // ローディング終了
  stopLoading: () => dispatch({ type: 'STOP_LOADING' }),
});

export default connect(mapStateToProps, mapDispatchToProps)(App);

useState フック

シンプルなアプリケーションであれば、useState フックで十分です。

Suspense フック

非同期コンポーネントを使用する場合は、Suspense フックがおすすめです。

Redux

複数のコンポーネントでローディング状態を共有する必要がある場合は、Redux を使用すると便利です。

DOM レンダリング中にローディング画面を表示するには、いくつかの方法があります。 それぞれの方法のメリットとデメリットを理解して、アプリケーションに合った方法を選択してください。




useState フックを使用する

const App = () => {
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    // データフェッチなどの非同期処理
    setTimeout(() => {
      setIsLoading(false);
    }, 1000);
  }, []);

  return (
    <div>
      {isLoading && <LoadingScreen />}
      {!isLoading && <MyComponent />}
    </div>
  );
};

const LoadingScreen = () => {
  return (
    <div>
      <h1>Loading...</h1>
    </div>
  );
};

const MyComponent = () => {
  return (
    <div>
      <h1>This is MyComponent</h1>
    </div>
  );
};

Suspense フックを使用する

const App = () => {
  return (
    <Suspense fallback={<LoadingScreen />}>
      <MyAsyncComponent />
    </Suspense>
  );
};

const MyAsyncComponent = () => {
  // データフェッチなどの非同期処理
  const data = await fetchData();
  return <MyComponent data={data} />;
};

const LoadingScreen = () => {
  return (
    <div>
      <h1>Loading...</h1>
    </div>
  );
};

const MyComponent = ({ data }) => {
  return (
    <div>
      <h1>This is MyComponent</h1>
      <p>{data}</p>
    </div>
  );
};

Redux を使用する

const App = () => {
  const { isLoading } = useSelector(state => state.loading);

  return (
    <div>
      {isLoading && <LoadingScreen />}
      {!isLoading && <MyComponent />}
    </div>
  );
};

const mapStateToProps = state => ({
  isLoading: state.loading.isLoading,
});

const mapDispatchToProps = dispatch => ({
  // ローディング開始
  startLoading: () => dispatch({ type: 'START_LOADING' }),
  // ローディング終了
  stopLoading: () => dispatch({ type: 'STOP_LOADING' }),
});

export default connect(mapStateToProps, mapDispatchToProps)(App);

const LoadingScreen = () => {
  return (
    <div>
      <h1>Loading...</h1>
    </div>
  );
};

const MyComponent = () => {
  return (
    <div>
      <h1>This is MyComponent</h1>
    </div>
  );
};

const reducers = {
  loading: (state = { isLoading: false }, action) => {
    switch (action.type) {
      case 'START_LOADING':
        return { ...state, isLoading: true };
      case 'STOP_LOADING':
        return { ...state, isLoading: false };
      default:
        return state;
    }
  },
};

const store = createStore(reducers);

export default store;

補足

  • 上記のサンプルコードは、あくまでも一例です。
  • アプリケーションの要件に合わせて、コードを修正してください。



DOM レンダリング中にローディング画面を表示するその他の方法

CSS アニメーションを使用する

<div class="loading-indicator">
  <div class="spinner"></div>
</div>
.loading-indicator {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 9999;
}

.spinner {
  width: 50px;
  height: 50px;
  border: 10px solid #fff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

ライブラリを使用する

react-loading などのライブラリを使用して、ローディング画面を表示できます。

import ReactLoading from 'react-loading';

const App = () => {
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    // データフェッチなどの非同期処理
    setTimeout(() => {
      setIsLoading(false);
    }, 1000);
  }, []);

  return (
    <div>
      {isLoading && <ReactLoading type="spinner" color="#fff" />}
      {!isLoading && <MyComponent />}
    </div>
  );
};

const MyComponent = () => {
  return (
    <div>
      <h1>This is MyComponent</h1>
    </div>
  );
};

どの方法を選択するかは、アプリケーションの要件と開発者の好みによって異なります。

  • シンプルなアプリケーションであれば、CSS アニメーションを使用するのが簡単です。
  • より複雑なアプリケーションであれば、ライブラリを使用すると便利です。

reactjs asynchronous redux


React.jsでDate型プロパティのバリデーション - サンプルコード付き

prop-typesライブラリをインストールします。Date型プロパティの型定義は以下のコードのように行います。このコードでは、dateプロパティがDate型のオブジェクトであることを検証しています。検証エラーが発生した場合、コンソールに警告が出力されます。...


React.jsボタン無効化の教科書:無効化のベストプラクティスと詳細ガイド

disabled 属性を使うHTMLの button 要素には、disabled 属性があります。この属性を true に設定すると、ボタンが無効になります。useState フックを使って、ボタンの状態を管理することもできます。ボタンの状態を true に設定すると、ボタンが無効になります。...


React Hook "useState" を Context API と使う

原因useState フックは、コンポーネントの状態を管理するために使用されます。React 16. 8 以降では、関数コンポーネント内で状態を管理するために useState フックを使用する必要があります。解決策このエラーを解決するには、以下のいずれかの方法で useState フックを使用する必要があります。...


JavaScriptエンジニア必見!React Hooksにおける「React has detected a change in the order of Hooks」エラーの解決策を網羅

このエラーメッセージは、React Hooksの呼び出し順序が変更されたことを示しています。React Hooksは、Reactコンポーネント内で状態や副作用を管理するための機能です。Hooksは常に同じ順序で呼び出される必要があるため、このエラーが発生します。...


React Nativeで別のVirtualizedListコンテナを使用する方法

この問題を解決するには、以下のいずれかの方法で別のVirtualizedListコンテナを使用できます。ネストされたリストの向きを変える例:垂直方向のScrollView内に水平方向のFlatListを使用する。SectionListまたはFlatGridのような別のコンポーネントを使用する...