P粉4398045142023-09-03 16:06:45
因此,這確實取決於程式碼的執行方式,特別是 setState 的非同步性質,因此您可以使用 setState 的回呼形式。這是一個例子:
setBlobs(prevBlobs => [...prevBlobs, res._bodyBlob]);
這是包含其餘程式碼的完整範例:
const capturePhoto = async () => { const photo = await camera.current.takePhoto(); fetch(photo.path) .then(res => { setBlobs(prevBlobs => [...prevBlobs, res._bodyBlob]); console.log('blobs', blobs.length, blobs); }) .catch(err => { console.log('err', err); }); checkLength(); }; const checkLength = async () => { if (blobs.length >= 2) { // upload files to a folder with the current date in a firebase cloud bucket const datestring = new Date().toLocaleString('de-DE'); blobs.forEach((blob, i) => { uploadFile(blob, datestring + '/' + (i + 1) + '.jpg'); }); // reset state setBlobs([]); sendNotification('Photos uploaded'); toggleDialog(); } };
P粉7757237222023-09-03 16:04:09
看起來像三件事:
checkLength
。 setState
的新值。這是 React 的基本想法(是否是個好主意還有待商榷),狀態值在渲染期間是不可變的。 setState
只是給出下一個渲染將使用的下一個不可變狀態。 setState
依賴先前的狀態時,您應該將回呼傳遞給setState
,而不是直接使用目前值。舉個例子,假設你有一個空數組,你呼叫 fetch 一次,然後在第一個數組完成之前再次呼叫 fetch 。在執行 ...blob
時,這兩個 setState
呼叫都會引用空數組。透過傳遞回調,setState
取得作為參數傳入的最新值。更多資訊: https://react.dev/reference/react/Component#setstate 最簡單的解決方案是將陣列作為參數傳遞給 setState
回呼內的 checkLength
。
這是問題中的 .then()
:
const capturePhoto = async () => { const photo = await camera.current.takePhoto(); fetch(photo.path) .then(res => { setBlobs(prev => { const newBlobs = [...prev, res._bodyBlob]; console.log('blobs', newBlobs.length, newBlobs); checkLength(newBlobs); return newBlobs; }); }) .catch(err => { console.log('err', err); }); };
這是async
await
const capturePhoto = async () => { const photo = await camera.current.takePhoto(); const res = await fetch(photo.path).catch(console.error); if (!res) return; setBlobs(prev => { const newBlobs = [...prev, res._bodyBlob]; console.log('blobs', newBlobs.length, newBlobs); checkLength(newBlobs); return newBlobs; }); };
檢查長度
const checkLength = async (newBlobs) => { if (newBlobs.length >= 2) { // upload files to a folder with the current date in a firebase cloud bucket const datestring = new Date().toLocaleString('de-DE'); newBlobs.forEach((blob, i) => { uploadFile(blob, datestring + '/' + (i + 1) + '.jpg'); }); // reset state setBlobs([]); sendNotification('Photos uploaded'); toggleDialog(); } };