Why can't I reset the array using setState?
P粉714890053
2023-09-02 23:44:06
<p>In my camera component I want to upload photos to a bucket every 3rd photo. I'm using state in React to save an image blob into an array. Everything works fine for the first 3 photos, but after that, I can't reset the array to empty and a seemingly random number of photos get uploaded to my bucket. </p>
<pre class="brush:js;toolbar:false;"> let [blobs, setBlobs] = useState([]);
const capturePhoto = async () => {
const photo = await camera.current.takePhoto();
fetch(photo.path)
.then(res => {
setBlobs([...blobs, 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();
}
};
</pre>
<p>I logged my array via console and the size only increased. Also, it starts console logging from scratch even though I've added an element, probably because <code>setState()</code> is asynchronous.
I tried to wait for the reset by wrapping it in a promise, but unfortunately that didn't work either.
Once there are 3 blobs, how do I upload them to the cloud and reset the list afterwards? </p>
So it really depends on how the code is executed, specifically the asynchronous nature of setState so you can use the callback form of setState. Here is an example:
Here is the complete example with the rest of the code:
Looks like three things:
checkLength
before the fetch is complete.setState
until the next render. This is the basic idea of React (whether it's a good idea is debatable), state values are immutable during rendering.setState
Just gives the next immutable state that will be used by the next render.setState
depends on a previous state, you should pass a callback tosetState
rather than using the current value directly. For example, let's say you have an empty array, you call fetch once, and then call fetch again before the first array is completed. BothsetState
calls will reference empty arrays when executing...blob
. By passing a callback,setState
gets the latest value passed in as a parameter. More information: https://react.dev/reference/react/Component#setstateThe simplest solution is to pass the array as a parameter to
checkLength
inside thesetState
callback.This is
.then()
in the question:This is
async
await
Check length