カメラ コンポーネントで、3 枚目ごとに写真をバケットにアップロードしたいと考えています。 React で状態を使用して画像 BLOB を配列に保存しています。最初の 3 枚の写真はすべて正常に機能しますが、それ以降は配列を空にリセットできず、一見ランダムな数の写真がバケットにアップロードされます。
let [blobs, setBlobs] = useState([]); const CapturePhoto = async () => { const photo = await カメラ.current.takePhoto(); フェッチ(写真.パス) .then(res => { setBlobs([...blobs, res._bodyBlob]); console.log('blobs', blob.length, blob); }) .catch(err => { console.log('err', err); }); checkLength(); }; const checkLength = async () => { if (blobs.length >= 2) { // Firebase クラウド バケット内の現在の日付のフォルダーにファイルをアップロードします const datestring = new Date().toLocaleString('de-DE'); blob.forEach((blob, i) => { UploadFile(blob, datestring '/' (i 1) '.jpg'); }); // 状態をリセット setBlobs([]); sendNotification('写真がアップロードされました'); トグルダイアログ(); } };
コンソール経由でアレイのログを記録しましたが、サイズは増加するだけでした。また、要素を追加したにもかかわらず、コンソールのログ記録が最初から開始されます。これは、おそらく setState()
が非同期であるためです。 Promiseでラップしてリセットを待ってみましたが、残念ながらそれもうまくいきませんでした。 3 つの BLOB がある場合、それらをクラウドにアップロードし、後でリストをリセットするにはどうすればよいですか?
つまり、実際にはコードの実行方法、特に setState の非同期の性質に依存するため、setState のコールバック形式を使用できます。以下に例を示します:
リーリーコードの残りの部分を含む完全な例を次に示します:
リーリー次の 3 つのことが考えられます:
checkLength
を呼び出します。setState
の新しい値は取得されません。これは React の基本的な考え方であり (これが良いアイデアかどうかは議論の余地があります)、状態値はレンダリング中に不変です。setState
次のレンダリングで使用される次の不変状態を与えるだけです。setState
が以前の状態に依存する場合、現在の値を直接使用するのではなく、コールバックをsetState
に渡す必要があります。たとえば、空の配列があり、fetch を 1 回呼び出して、最初の配列が完了する前に再度 fetch を呼び出したとします。両方のsetState
呼び出しは、...blob
の実行時に空の配列を参照します。コールバックを渡すことにより、setState
はパラメータとして渡された最新の値を取得します。詳細:https://react.dev/reference/react/Component#setstate最も簡単な解決策は、
setState
コールバック内のcheckLength
にパラメータとして配列を渡すことです。これは質問の
リーリー.then()
です:これは
リーリー非同期
await
リーリー長さの確認