検索

ホームページ  >  に質問  >  本文

書き換えられたタイトルは次のとおりです。promise.then() の各 setState がレンダリングされる前に React Promise.all().then() を呼び出す

<p>テーブルに表示するためにリモート リソースに対して 200 件の呼び出しを実行しようとしています。同時に、残りの呼び出し数を示す進行状況バーを表示します。 </p> <p>この例を使用して、<code>Fetch()</code> と <code>Promise.all()</code> を使用して <code>setState()< を呼び出す方法を示します。 /code> 新しいデータを更新します。 </p> <p>私の問題は、各 Promise の <code>.then()</code> にあり、これは何らかのロジックを計算し、<code>setState()</code> を呼び出してデータを更新します。 </p> <p>私の進行状況バーは、<code>Object.keys(data).length</code> を使用して進行状況を表示します。 </p> <p><code>Promise.all()</code> が「Complete」状態をトリガーし、進行状況バーが削除された後も、Promise 自体はまだ <code>then()</code> を呼び出しています。これにより、解決されたすべての Promise が表示される前に進行状況バーが非表示になります。 </p> <p>この問題に正しく対処するにはどうすればよいですか? </p>
<p>デモでは、<code>setTimeout()</code> を使用して、高価なロジックをシミュレートします。 </p> <p>問題は、<code>Promise.all.then: 20</code> が <code>Render 20</code> の後にある必要があることです。 </p> <pre class="brush:none;toolbar:false;">レンダリング 0 ... レンダリング 12 Promise.all.then: 20 # 各レンダリング後にこれを記録する必要があります レンダリング 13 ... レンダリング 19 レンダリング 20 </pre> <p>デモで問題を示すために、進行状況バーが完全に埋まる前に削除されました (赤色に変わりました)。</p> <p><br /></p> <pre class="brush:js;toolbar:false;">const { useState } = React; const 例 = () => { const [done, setDone] = useState(false); const [データ, setData] = useState({}); const demoData = Array.from(Array(20).keys()); const demoResolver = (x) =>新しい Promise(res => setTimeout(() => res(x), Math.random() * 1250)) constloadData = () => { const Promise = DemonData.map(c =>demoResolver(c)); Promise.forEach(promise => { 約束 .then(r => { setTimeout(() => { setData(p => ({ ...p, [r]: r })); }, 500); }) }); Promise.all(約束) .then(r => { console.log('Promise.all.then: ', r.length) setDone(true); }) } console.log('Render', Object.keys(data).length); const progressBarIsShownDebugColor = (完了) ? 「危険です」 : '情報です'; 戻る ( <セクションクラス名='セクション'> <h1 className='title is-3'>{'例'}</h1> <進捗状況 max={demoData.length} 値={オブジェクト.キー(データ).長さ} className={'progress my-3 ' progressBarIsShownDebugColor} /> <button onClick={loadData}>開始</button> </セクション> ) } ReactDOM.render(<Example />, document.getElementById("react"));</pre> <pre class="brush:css;toolbar:false;">.as-console-wrapper { max-height: 50px !重要; }</pre> <pre class="brush:html;toolbar:false;"><script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min .js"> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script> <リンク rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css"> <div id="react"></div></pre> <p><br /></p>
P粉162773626P粉162773626466日前407

全員に返信(1)返信します

  • P粉426780515

    P粉4267805152023-08-21 00:02:16

    上記のコードに示されている問題は、データを取得した後、状態を設定するまでにさらに 500 ミリ秒の非同期遅延が発生することです。実際のコードでは、.all の後に setData を呼び出す追加の処理 (おそらく同期) があるように見えます。

    ベスト プラクティスは、done を個別の状態ではなく計算プロパティとして持つことです。その時点では、競合を設定するために状態に依存する必要がなく、Object .keys( data).length は十分に安価であるため、パフォーマンスに悪影響を与えることはありません (また、他の領域でも使用できます。問題になった場合は、変数にキャッシュできます)。

    リーリー

    リーリー リーリー リーリー

    返事
    0
  • キャンセル返事