cari

Rumah  >  Soal Jawab  >  teks badan

Mengapa saya tidak boleh menetapkan semula tatasusunan menggunakan setState?

<p>Dalam komponen kamera saya, saya mahu memuat naik foto ke baldi setiap foto ke-3. Saya menggunakan keadaan dalam React untuk menyimpan gumpalan imej ke dalam tatasusunan. Semuanya berfungsi dengan baik untuk 3 foto pertama, tetapi selepas itu, saya tidak boleh menetapkan semula tatasusunan kepada kosong dan bilangan foto yang kelihatan rawak dimuat naik ke baldi saya. </p> <pre class="brush:js;toolbar:false;"> biarkan [blobs, setBlobs] = useState([]); const capturePhoto = tak segerak () => foto const = tunggu camera.current.takePhoto(); ambil(photo.path) .then(res => { setBlobs([...blobs, res._bodyBlob]); console.log('gumpalan', gumpalan.panjang, gumpalan); }) .catch(err => { console.log('err', err); }); checkLength(); }; const checkLength = tak segerak () => if (blobs.length >= 2) { // muat naik fail ke folder dengan tarikh semasa dalam baldi awan firebase const datestring = new Date().toLocaleString('de-DE'); blobs.forEach((blob, i) => { uploadFile(blob, datestring + '/' + (i + 1) + '.jpg'); }); // set semula keadaan setBlobs([]); sendNotification('Foto dimuat naik'); toggleDialog(); } }; </pra> <p>Saya melog tatasusunan saya melalui konsol dan saiznya hanya meningkat. Selain itu, ia memulakan pengelogan konsol dari awal walaupun saya telah menambah elemen, mungkin kerana <code>setState()</code> Saya cuba menunggu tetapan semula dengan membungkusnya dengan janji, tetapi malangnya ia tidak berjaya juga. Sebaik sahaja terdapat 3 gumpalan, bagaimana saya boleh memuat naiknya ke awan dan menetapkan semula senarai selepas itu? </p>
P粉714890053P粉714890053454 hari yang lalu584

membalas semua(2)saya akan balas

  • P粉439804514

    P粉4398045142023-09-03 16:06:45

    Jadi ia sangat bergantung pada cara kod dilaksanakan, khususnya sifat tak segerak setState supaya anda boleh menggunakan bentuk panggilan balik setState . Berikut adalah contoh:

    setBlobs(prevBlobs => [...prevBlobs, res._bodyBlob]);

    Berikut ialah contoh lengkap dengan selebihnya kod:

    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();
      }
    };

    balas
    0
  • P粉775723722

    P粉7757237222023-09-03 16:04:09

    Nampak seperti tiga perkara:

    1. Tidak menunggu panggilan ambil, panggil checkLength sebelum pengambilan selesai.
    2. Anda tidak mendapat setState 的新值。这是 React 的基本思想(是否是个好主意还有待商榷),状态值在渲染期间是不可变的。 setState sehingga pemaparan seterusnya, hanya keadaan tidak berubah seterusnya yang akan digunakan oleh pemaparan seterusnya.
    3. BilasetState依赖于先前的状态时,您应该将回调传递给setState,而不是直接使用当前值。举个例子,假设你有一个空数组,你调用 fetch 一次,然后在第一个数组完成之前再次调用 fetch 。在执行 ...blob 时,这两个 setState 调用都会引用空数组。通过传递回调,setState Dapatkan nilai terkini yang dihantar sebagai parameter. Maklumat lanjut: https://react.dev/reference/react/Component#setstate

    Penyelesaian paling mudah ialah menghantar tatasusunan sebagai hujah kepada setState 回调内的 checkLength di dalam panggilan balik setState.

    Ini ialah .then() yang dimaksudkan:

      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);
          });
      };
    

    Ini ialahasync 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();
        }
      };
    

    balas
    0
  • Batalbalas