著者は、 Creative Commons を選択して、 Write forDOnationsプログラムの一環として寄付を受け取りました。

序章

JavaScript Web開発者として、非同期コードを使用すると、コードの一部を実行しながら、他の部分がデータを待機または解決することができます。 これは、アプリの重要な部分がレンダリングされる前に、重要性の低い部分を待つ必要がないことを意味します。 非同期コードを使用すると、新しい情報を要求して表示することでアプリケーションを更新することもでき、長い関数や要求がバックグラウンドで処理されている場合でもユーザーにスムーズなエクスペリエンスを提供します。

React 開発では、非同期プログラミングには固有の問題があります。 たとえば、React 機能コンポーネントを使用する場合、非同期関数は無限のループを作成する可能性があります。 コンポーネントがロードされると、非同期関数を開始できます。非同期関数が解決されると、再レンダリングがトリガーされ、コンポーネントが非同期関数を呼び出すことができます。 このチュートリアルでは、useEffect と呼ばれる特別なフックを使用してこれを回避する方法を説明します。このフックは、特定のデータが変更された場合にのみ関数を実行します。 これにより、各レンダリングサイクルではなく、意図的に非同期コードを実行できるようになります。

非同期コードは、新しいデータの要求だけに限定されません。 Reactには、遅延読み込みコンポーネント、またはユーザーが必要な場合にのみそれらを読み込むためのシステムが組み込まれています。 Create ReactAppのデフォルトのwebpack構成と組み合わせると、コードを分割して、大きなアプリケーションを必要に応じてロードできる小さな部分に縮小できます。 Reactには特別なコンポーネントがあります Suspense ブラウザが新しいコンポーネントをロードしている間、プレースホルダーが表示されます。 Reactの将来のバージョンでは、次を使用できるようになります Suspense レンダリングをブロックせずにネストされたコンポーネントにデータをロードします。

このチュートリアルでは、河川に関する情報を表示し、Web APIへのリクエストをシミュレートするアプリを作成して、Reactで非同期データを処理します。 setTimeout. このチュートリアルの終わりまでに、を使用して非同期データをロードできるようになります。 useEffect 針。 また、データ解決の前にコンポーネントがアンマウントされた場合でも、エラーを発生させることなくページを安全に更新できます。 最後に、コード分割を使用して、大きなアプリケーションを小さな部分に分割します。

前提条件

ステップ1—で非同期データをロードする useEffect

このステップでは、 useEffect 非同期データをサンプルアプリケーションにロードするためのフック。 フックを使用して、不要なデータフェッチを防ぎ、データの読み込み中にプレースホルダーを追加し、データが解決されたときにコンポーネントを更新します。 この手順を完了すると、次のデータを読み込むことができるようになります。 useEffect を使用してデータを設定します useState 解決したらフックします。

このトピックを探索するために、世界で最も長い川に関する情報を表示するアプリケーションを作成します。 外部データソースへのリクエストをシミュレートする非同期関数を使用してデータをロードします。

まず、というコンポーネントを作成します RiverInformation. ディレクトリを作成します。

  1. mkdir src/components/RiverInformation

開ける RiverInformation.js テキストエディタの場合:

  1. nano src/components/RiverInformation/RiverInformation.js

次に、プレースホルダーコンテンツを追加します。

async-tutorial / src / components / RiverInformation / RiverInformation.js
import React from 'react';

export default function RiverInformation() {
  return(
    <div>
      <h2>River Information</h2>
    </div>
  )
}

ファイルを保存して閉じます。 次に、新しいコンポーネントをインポートしてルートコンポーネントにレンダリングする必要があります。 開ける App.js:

  1. nano src/components/App/App.js

強調表示されたコードを追加して、コンポーネントをインポートしてレンダリングします。

async-tutorial / src / components / App / App.js
import React from 'react';
import './App.css';
import RiverInformation from '../RiverInformation/RiverInformation';

function App() {
  return (
    <div className="wrapper">
      <h1>World's Longest Rivers</h1>
      <RiverInformation />
    </div>
  );
}

export default App;

ファイルを保存して閉じます。

最後に、アプリを読みやすくするために、スタイルを追加します。 開ける App.css:

  1. nano src/components/App/App.css

にパディングを追加します wrapper CSSを次のように置き換えてクラスを作成します。

async-tutorial / src / components / App / App.css
.wrapper {
    padding: 20px
}

ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、基本コンポーネントがレンダリングされます。

このチュートリアルでは、データを返すための汎用サービスを作成します。 サービスとは、特定のタスクを実行するために再利用できるコードを指します。 コンポーネントは、サービスがその情報を取得する方法を知る必要はありません。 知っておく必要があるのは、サービスがPromiseを返すことだけです。 この場合、データリクエストは次のようにシミュレートされます setTimeout、データを提供する前に指定された時間待機します。

と呼ばれる新しいディレクトリを作成します servicessrc/ ディレクトリ:

  1. mkdir src/services

このディレクトリには、非同期機能が保持されます。 というファイルを開きます rivers.js:

  1. nano src/services/rivers.js

ファイル内で、という関数をエクスポートします getRiverInformation それは約束を返します。 約束の中に、 setTimeout 後に約束を解決する関数 1500 ミリ秒。 これにより、データが解決されるのを待っている間にコンポーネントがどのようにレンダリングされるかを確認する時間ができます。

async-tutorial / src / services / rivers.js
export function getRiverInformation() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        continent: 'Africa',
        length: '6,650 km',
        outflow: 'Mediterranean'
      })
    }, 1500)
  })
}

このスニペットでは、河川情報をハードコーディングしていますが、この関数は、API呼び出しなど、使用する可能性のある非同期関数と同様です。 重要な部分は、コードがpromiseを返すことです。

ファイルを保存して閉じます。

データを返すサービスができたので、それをコンポーネントに追加する必要があります。 これにより、問題が発生する場合があります。 コンポーネント内で非同期関数を呼び出してから、を使用してデータを変数に設定するとします。 useState 針。 コードは次のようになります。

import React, { useState } from 'react';
import { getRiverInformation } from '../../services/rivers';

export default function RiverInformation() {
  const [riverInformation, setRiverInformation] = useState({});

  getRiverInformation()
  .then(d => {
    setRiverInformation(d)
  })

  return(
    ...
  )
}

データを設定すると、フックを変更するとコンポーネントが再レンダリングされます。 コンポーネントが再レンダリングされると、 getRiverInformation 関数は再び実行され、解決すると状態が設定され、別の再レンダリングがトリガーされます。 ループは永遠に続きます。

この問題を解決するために、Reactには特別なフックがあります useEffect これは、特定のデータが変更された場合にのみ実行されます。

useEffect フックは、最初の引数として function を受け入れ、2番目の引数としてトリガーのarrayを受け入れます。 この関数は、レイアウトとペイントの後の最初のレンダリングで実行されます。 その後、トリガーの1つが変更された場合にのみ実行されます。 空の配列を指定すると、1回だけ実行されます。 トリガーの配列を含めない場合、レンダリングのたびに実行されます。

開ける RiverInformation.js:

  1. nano src/components/RiverInformation/RiverInformation.js

使用 useState と呼ばれる変数を作成するためのフック riverInformation と呼ばれる関数 setRiverInformation. を設定してコンポーネントを更新します riverInformation 非同期関数が解決したとき。 次に、 getRiverInformation で機能する useEffect. 必ず2番目の引数として空の配列を渡してください。 約束が解決したら、更新します riverInformation とともに setRiverInformation 関数:

async-tutorial / src / components / RiverInformation / RiverInformation.js
import React, { useEffect, useState } from 'react';
import { getRiverInformation } from '../../services/rivers';

export default function RiverInformation() {
  const [riverInformation, setRiverInformation] = useState({});

  useEffect(() => {
   getRiverInformation()
   .then(data =>
     setRiverInformation(data)
   );
  }, [])


  return(
    <div>
      <h2>River Information</h2>
      <ul>
        <li>Continent: {riverInformation.continent}</li>
        <li>Length: {riverInformation.length}</li>
        <li>Outflow: {riverInformation.outflow}</li>
      </ul>
    </div>
  )
}

非同期関数が解決したら、順序付けされていないリストを新しい情報で更新します。

ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、関数が解決された後にデータが表示されます。

データがロードされる前にコンポーネントがレンダリングされることに注意してください。 非同期コードの利点は、最初のレンダリングがブロックされないことです。 この場合、データなしでリストを表示するコンポーネントがありますが、スピナーまたはスケーラブルベクターグラフィック(SVG)プレースホルダーをレンダリングすることもできます。

ユーザー情報や変更されないリソースのリストを取得している場合など、データを1回だけロードする必要がある場合があります。 しかし、多くの場合、非同期関数にはいくつかの引数が必要になります。 そのような場合は、使用をトリガーする必要があります useEffect データが変更されるたびにフックします。

これをシミュレートするには、サービスにデータを追加します。 開ける rivers.js:

  1. nano src/services/rivers.js

次に、さらにいくつかの河川のデータを含むオブジェクトを追加します。 に基づいてデータを選択します name 口論:

async-tutorial / src / services / rivers.js
const rivers = {
 nile: {
   continent: 'Africa',
   length: '6,650 km',
   outflow: 'Mediterranean'
 },
 amazon: {
   continent: 'South America',
   length: '6,575 km',
   outflow: 'Atlantic Ocean'
 },
 yangtze: {
   continent: 'Asia',
   length: '6,300 km',
   outflow: 'East China Sea'
 },
 mississippi: {
   continent: 'North America',
   length: '6,275 km',
   outflow: 'Gulf of Mexico'
 }
}

export function getRiverInformation(name) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(
        rivers[name]
      )
    }, 1500)
  })
}

ファイルを保存して閉じます。 次に、開く App.js したがって、さらにオプションを追加できます。

  1. nano src/components/App/App.js

中身 App.js stateful 変数を作成し、選択した川を保持する関数を作成します。 useState 針。 次に、各川のボタンを追加します。 onClick 選択した河川を更新するハンドラー。 合格 riverRiverInformation propを使用して name:

async-tutorial / src / components / App / App.js
import React, { useState } from 'react';
import './App.css';
import RiverInformation from '../RiverInformation/RiverInformation';

function App() {
  const [river, setRiver] = useState('nile');
  return (
    <div className="wrapper">
      <h1>World's Longest Rivers</h1>
      <button onClick={() => setRiver('nile')}>Nile</button>
      <button onClick={() => setRiver('amazon')}>Amazon</button>
      <button onClick={() => setRiver('yangtze')}>Yangtze</button>
      <button onClick={() => setRiver('mississippi')}>Mississippi</button>
      <RiverInformation name={river} />
    </div>
  );
}

export default App;

ファイルを保存して閉じます。 次に、開く RiverInformation.js:

  1. nano src/components/RiverInformation/RiverInformation.js

引き込む name 小道具として、それを getRiverInformation 関数。 必ず追加してください name の配列に useEffect、それ以外の場合は再実行されません:

async-tutorial / src / components / RiverInformation / RiverInformation.js
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { getRiverInformation } from '../../services/rivers';

export default function RiverInformation({ name }) {
  const [riverInformation, setRiverInformation] = useState({});

  useEffect(() => {
    getRiverInformation(name)
    .then(data =>
      setRiverInformation(data)
    );
  }, [name])


  return(
    <div>
      <h2>River Information</h2>
      <ul>
        <li>Continent: {riverInformation.continent}</li>
        <li>Length: {riverInformation.length}</li>
        <li>Outflow: {riverInformation.outflow}</li>
      </ul>
    </div>
  )
}

RiverInformation.propTypes = {
 name: PropTypes.string.isRequired
}

このコードでは、弱いタイピングシステムも追加しました PropTypes、小道具が文字列であることを確認します。

ファイルを保存します。 これを行うと、ブラウザが更新され、さまざまな川を選択できます。 クリックしてからデータがレンダリングされるまでの遅延に注意してください。

あなたが省略した場合 name からの小道具 useEffect アレイの場合、ブラウザコンソールでビルドエラーが発生します。 これは次のようになります。

Error
Compiled with warnings. ./src/components/RiverInformation/RiverInformation.js Line 13:6: React Hook useEffect has a missing dependency: 'name'. Either include it or remove the dependency array react-hooks/exhaustive-deps Search for the keywords to learn more about each warning. To ignore, add // eslint-disable-next-line to the line before.

このエラーは、エフェクト内の関数に、明示的に設定していない依存関係があることを示しています。 この状況では、効果が機能しないことは明らかですが、propデータをコンポーネント内のステートフルデータと比較している場合があります。これにより、配列内のアイテムを追跡できなくなる可能性があります。

最後に行うことは、コンポーネントに防御プログラミングを追加することです。 これは、アプリケーションの高可用性を強調する設計原則です。 データが正しい形状でない場合や、APIリクエストからデータをまったく取得しない場合でも、コンポーネントが確実にレンダリングされるようにする必要があります。

アプリが現在のように、エフェクトは更新されます riverInformation 受け取るあらゆる種類のデータで。 これは通常オブジェクトになりますが、そうでない場合は、オプションのチェーンを使用して、エラーがスローされないようにすることができます。

中身 RiverInformation.js、オブジェクトドットチェーンのインスタンスをオプションのチェーンに置き換えます。 動作するかどうかをテストするには、デフォルトのオブジェクトを削除します {} から useState 関数:

async-tutorial / src / components / RiverInformation / RiverInformation.js
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { getRiverInformation } from '../../services/rivers';

export default function RiverInformation({ name }) {
  const [riverInformation, setRiverInformation] = useState();

  useEffect(() => {
    getRiverInformation(name)
    .then(data =>
      setRiverInformation(data)
    );
  }, [name])

  return(
    <div>
      <h2>River Information</h2>
      <ul>
        <li>Continent: {riverInformation?.continent}</li>
        <li>Length: {riverInformation?.length}</li>
        <li>Outflow: {riverInformation?.outflow}</li>
      </ul>
    </div>
  )
}

RiverInformation.propTypes = {
  name: PropTypes.string.isRequired
}

ファイルを保存して閉じます。 これを行うと、コードが上のプロパティを参照している場合でも、ファイルは引き続き読み込まれます。 undefined オブジェクトの代わりに:

通常、防御プログラミングはベストプラクティスと見なされますが、応答を保証できない場合のAPI呼び出しなどの非同期関数では特に重要です。

このステップでは、Reactで非同期関数を呼び出しました。 あなたは useEffect 再レンダリングをトリガーせずに情報をフェッチし、条件を追加して新しい更新をトリガーするためのフック useEffect 配列。

次のステップでは、コンポーネントがマウントされたときにのみコンポーネントが更新されるように、アプリにいくつかの変更を加えます。 これは、アプリがメモリリークを回避するのに役立ちます。

ステップ2—マウントされていないコンポーネントでのエラーの防止

この手順では、マウントされていないコンポーネントのデータが更新されないようにします。 非同期プログラミングではデータがいつ解決されるかわからないため、コンポーネントが削除された後にデータが解決されるリスクは常にあります。 マウントされていないコンポーネントのデータを更新することは非効率的であり、アプリが必要以上のメモリを使用しているメモリリークを引き起こす可能性があります。

この手順を完了すると、ガードを追加してメモリリークを防ぐ方法がわかります。 useEffect コンポーネントがマウントされている場合にのみデータを更新するためのフック。

現在のコンポーネントは常にマウントされるため、 DOM から削除された後、コードがコンポーネントを更新しようとする可能性はありませんが、ほとんどのコンポーネントはそれほど信頼性がありません。 これらは、ユーザーがアプリケーションを操作するときにページに追加され、ページから削除されます。 非同期関数が解決される前にコンポーネントがページから削除されると、メモリリークが発生する可能性があります。

問題をテストするには、更新します App.js 川の詳細を追加および削除できるようにします。

開ける App.js:

  1. nano src/components/App/App.js

川の詳細を切り替えるボタンを追加します。 使用 useReducer 詳細を切り替える関数と、切り替えられた状態を格納する変数を作成するためのフック:

async-tutorial / src / components / App / App.js
import React, { useReducer, useState } from 'react';
import './App.css';
import RiverInformation from '../RiverInformation/RiverInformation';

function App() {
  const [river, setRiver] = useState('nile');
  const [show, toggle] = useReducer(state => !state, true);
  return (
    <div className="wrapper">
      <h1>World's Longest Rivers</h1>
      <div><button onClick={toggle}>Toggle Details</button></div>
      <button onClick={() => setRiver('nile')}>Nile</button>
      <button onClick={() => setRiver('amazon')}>Amazon</button>
      <button onClick={() => setRiver('yangtze')}>Yangtze</button>
      <button onClick={() => setRiver('mississippi')}>Mississippi</button>
      {show && <RiverInformation name={river} />}
    </div>
  );
}

export default App;

ファイルを保存します。 ブラウズを実行するとリロードされ、詳細を切り替えることができます。

川をクリックし、すぐに Toggle Details ボタンをクリックして、詳細を非表示にします。 Reactは、潜在的なメモリリークがあることを警告するエラーを生成します。

この問題を修正するには、内部の非同期関数をキャンセルまたは無視する必要があります useEffect. RxJS などのライブラリを使用している場合は、コンポーネントがマウント解除されたときに、関数を返すことで非同期アクションをキャンセルできます。 useEffect 針。 それ以外の場合は、マウントされた状態を格納するための変数が必要になります。

開ける RiverInformation.js:

  1. nano src/components/RiverInformation/RiverInformation.js

内部 useEffect 関数、と呼ばれる変数を作成します mounted に設定します true. 内部 .then コールバック、条件を使用してデータを設定する場合 mounted 本当です:

async-tutorial / src / components / RiverInformation / RiverInformation.js

import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { getRiverInformation } from '../../services/rivers';

export default function RiverInformation({ name }) {
  const [riverInformation, setRiverInformation] = useState();

  useEffect(() => {
    let mounted = true;
    getRiverInformation(name)
    .then(data => {
      if(mounted) {
        setRiverInformation(data)
      }
    });
  }, [name])


  return(
    <div>
      <h2>River Information</h2>
      <ul>
        <li>Continent: {riverInformation?.continent}</li>
        <li>Length: {riverInformation?.length}</li>
        <li>Outflow: {riverInformation?.outflow}</li>
      </ul>
    </div>
  )
}

RiverInformation.propTypes = {
  name: PropTypes.string.isRequired
}

変数ができたので、コンポーネントがアンマウントされたときにそれを反転できるようにする必要があります。 とともに useEffect フック、コンポーネントがアンマウントされたときに実行される関数を返すことができます。 設定する関数を返します mountedfalse:

async-tutorial / src / components / RiverInformation / RiverInformation.js

import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { getRiverInformation } from '../../services/rivers';

export default function RiverInformation({ name }) {
  const [riverInformation, setRiverInformation] = useState();

  useEffect(() => {
    let mounted = true;
    getRiverInformation(name)
    .then(data => {
      if(mounted) {
        setRiverInformation(data)
      }
    });
    return () => {
     mounted = false;
   }
  }, [name])

  return(
    <div>
      <h2>River Information</h2>
      <ul>
        <li>Continent: {riverInformation?.continent}</li>
        <li>Length: {riverInformation?.length}</li>
        <li>Outflow: {riverInformation?.outflow}</li>
      </ul>
    </div>
  )
}

RiverInformation.propTypes = {
  name: PropTypes.string.isRequired
}

ファイルを保存します。 そうすると、エラーなしで詳細を切り替えることができます。

アンマウントすると、コンポーネント useEffect 変数を更新します。 非同期関数は引き続き解決されますが、マウントされていないコンポーネントには変更が加えられません。 これにより、メモリリークが防止されます。

この手順では、コンポーネントがマウントされている場合にのみアプリの更新状態を作成しました。 更新しました useEffect コンポーネントがマウントされているかどうかを追跡するためのフックと、コンポーネントがマウント解除されたときに値を更新する関数を返しました。

次のステップでは、コンポーネントを非同期的にロードして、コードを小さなバンドルに分割し、ユーザーが必要に応じてロードします。

ステップ3—コンポーネントの遅延読み込み Suspenselazy

このステップでは、Reactを使用してコードを分割します Suspenselazy. アプリケーションが大きくなるにつれて、最終的なビルドのサイズも大きくなります。 ユーザーにアプリケーション全体のダウンロードを強制するのではなく、コードを小さなチャンクに分割することができます。 React Suspenselazy webpackやその他のビルドシステムと連携して、コードを小さな部分に分割し、ユーザーがオンデマンドでロードできるようにします。 将来的には、使用できるようになります Suspense APIリクエストを含むさまざまなデータをロードします。

この手順を完了すると、コンポーネントを非同期でロードして、大きなアプリケーションをより小さく、より焦点を絞ったチャンクに分割できるようになります。

これまでは、データを非同期的にロードすることだけを扱ってきましたが、コンポーネントを非同期的にロードすることもできます。 このプロセスは、コード分割と呼ばれることが多く、コードバンドルのサイズを縮小するのに役立ちます。これにより、ユーザーがアプリケーションの一部のみを使用している場合でも、アプリケーション全体をダウンロードする必要がなくなります。

ほとんどの場合、コードを静的にインポートしますが、動的を呼び出すことでコードをインポートできます。 import ステートメントの代わりに関数として。 コードは次のようになります。

import('my-library')
.then(library => library.action())

Reactは、lazyと呼ばれる追加のツールセットを提供します。 Suspense. React Suspense 最終的にはデータ読み込みの処理に拡張されますが、今のところ、これを使用してコンポーネントを読み込むことができます。

開ける App.js:

  1. nano src/components/App/App.js

次にインポート lazySuspense から react:

async-tutorial / src / components / App / App.js
import React, { lazy, Suspense, useReducer, useState } from 'react';
import './App.css';
import RiverInformation from '../RiverInformation/RiverInformation';

function App() {
  const [river, setRiver] = useState('nile');
  const [show, toggle] = useReducer(state => !state, true);
  return (
    <div className="wrapper">
      <h1>World's Longest Rivers</h1>
      <div><button onClick={toggle}>Toggle Details</button></div>
      <button onClick={() => setRiver('nile')}>Nile</button>
      <button onClick={() => setRiver('amazon')}>Amazon</button>
      <button onClick={() => setRiver('yangtze')}>Yangtze</button>
      <button onClick={() => setRiver('mississippi')}>Mississippi</button>
      {show && <RiverInformation name={river} />}
    </div>
  );
}

export default App;

lazySuspsense 2つの異なる仕事があります。 あなたは lazy コンポーネントを動的にインポートして変数に設定する関数。 Suspense は、コードの読み込み中にフォールバックメッセージを表示するために使用する組み込みコンポーネントです。

交換 import RiverInformation from '../RiverInformation/RiverInformation'; に電話して lazy. 結果をという変数に割り当てます RiverInformation. 次にラップ {show && <RiverInformation name={river} />} とともに Suspense コンポーネントと <div> のメッセージで Loading Componentfallback 小道具:

async-tutorial / src / components / App / App.js
import React, { lazy, Suspense, useReducer, useState } from 'react';
import './App.css';
const RiverInformation = lazy(() => import('../RiverInformation/RiverInformation'));

function App() {
  const [river, setRiver] = useState('nile');
  const [show, toggle] = useReducer(state => !state, true);
  return (
    <div className="wrapper">
      <h1>World's Longest Rivers</h1>
      <div><button onClick={toggle}>Toggle Details</button></div>
      <button onClick={() => setRiver('nile')}>Nile</button>
      <button onClick={() => setRiver('amazon')}>Amazon</button>
      <button onClick={() => setRiver('yangtze')}>Yangtze</button>
      <button onClick={() => setRiver('mississippi')}>Mississippi</button>
      <Suspense fallback={<div>Loading Component</div>}>
        {show && <RiverInformation name={river} />}
      </Suspense>
    </div>
  );
}

export default App;

ファイルを保存します。 その場合、ページをリロードすると、コンポーネントが動的にロードされていることがわかります。 読み込み中のメッセージを表示したい場合は、ChromeWebブラウザで応答をスロットルできます。

ChromeまたはFirefoxネットワークタブに移動すると、コードがさまざまなチャンクに分割されていることがわかります。

各チャンクはデフォルトで番号を取得しますが、Create React Appをwebpackと組み合わせて使用すると、動的インポートによってコメントを追加することでチャンク名を設定できます。

App.js、コメントを追加 /* webpackChunkName: "RiverInformation" */import 関数:

async-tutorial / src / components / App / App.js
import React, { lazy, Suspense, useReducer, useState } from 'react';
import './App.css';
const RiverInformation = lazy(() => import(/* webpackChunkName: "RiverInformation" */ '../RiverInformation/RiverInformation'));

function App() {
  const [river, setRiver] = useState('nile');
  const [show, toggle] = useReducer(state => !state, true);
  return (
    <div className="wrapper">
      <h1>World's Longest Rivers</h1>
      <div><button onClick={toggle}>Toggle Details</button></div>
      <button onClick={() => setRiver('nile')}>Nile</button>
      <button onClick={() => setRiver('amazon')}>Amazon</button>
      <button onClick={() => setRiver('yangtze')}>Yangtze</button>
      <button onClick={() => setRiver('mississippi')}>Mississippi</button>
      <Suspense fallback={<div>Loading Component</div>}>
        {show && <RiverInformation name={river} />}
      </Suspense>
    </div>
  );
}

export default App;

ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、 RiverInformation チャンクには一意の名前が付けられます。

このステップでは、コンポーネントを非同期でロードします。 使いました lazySuspense コンポーネントを動的にインポートし、コンポーネントのロード中にロードメッセージを表示します。 また、読みやすさとデバッグを向上させるために、webpackチャンクにカスタム名を付けました。

結論

非同期機能は、効率的なユーザーフレンドリーなアプリケーションを作成します。 ただし、それらの利点には、プログラムのバグに発展する可能性のある微妙なコストが伴います。 これで、ユーザーに表示可能なアプリケーションを提供しながら、大きなアプリケーションを小さな部分に分割し、非同期データをロードできるツールができました。 この知識を使用して、APIリクエストと非同期データ操作をアプリケーションに組み込み、高速で信頼性の高いユーザーエクスペリエンスを作成できます。

Reactチュートリアルをもっと読みたい場合は、 Reactトピックページを確認するか、React.jsシリーズのコーディング方法ページに戻ってください。