다시 작성된 제목은 다음과 같습니다. promise.then()의 각 setState가 렌더링되기 전에 React Promise.all().then() 호출
<p>남은 호출 수를 표시하기 위해 진행률 표시줄을 표시하는 동시에 테이블에 표시하기 위해 원격 리소스에 200번의 호출을 시도하고 있습니다. </p>
<p>이 예제를 사용하여 <code>Fetch()</code> 및 <code>Promise.all()</code> / code>를 사용하여 새 데이터를 업데이트합니다. </p>
<p>내 문제는 각 약속의 <code>.then()</code>에 있습니다. 이 코드는 일부 논리를 계산한 다음 <code>setState()</code>를 호출하여 데이터를 업데이트합니다. </p>
<p>내 진행률 표시줄은 <code>Object.keys(data).length</code>를 사용하여 진행 상황을 표시합니다. </p>
<p><code>Promise.all()</code>가 "완료" 상태를 트리거하고 진행률 표시줄을 제거한 후에도 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 } = 반응;
const 예 = () => {
const [완료, setDone] = useState(false);
const [data, setData] = useState({});
const decoData = Array.from(Array(20).keys());
const 데모Resolver = (x) => new Promise(res => setTimeout(() => res(x), Math.random() * 1250))
const loadData = () => {
const promise = decoData.map(c => decoResolver(c));
promise.forEach(약속 => {
약속하다
.then(r => {
setTimeout(() => {
setData(p => ({ ...p, [r]: r }));
}, 500);
})
});
Promise.all(약속)
.then(r => {
console.log('Promise.all.then: ', r.length)
설정완료(true);
})
}
console.log('렌더링', Object.keys(data).length);
const ProgressBarIsShownDebugColor = (완료)
? '위험하다'
: '정보입니다';
반품 (
<section className='섹션'>
<h1 className='제목은-3'>{'예'}</h1>
<진행상황
최대={demoData.length}
값={Object.keys(data).length}
className={'progress my-3 ' + ProgressBarIsShownDebugColor}
/>
<button onClick={loadData}>시작</button>
</섹션>
)
}
ReactDOM.render(<예제 />, document.getElementById("react"));</pre>
<pre class="brush:css;toolbar:false;">.as-console-wrapper { 최대 높이: 50px !important; }</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>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
<div id="react"></div></pre>
<p><br /></p>