Estoy intentando convertir la siguiente función para que sea asíncrona en React (usando CompressorJS ):
const UploadImages = ({ jobInfo, setLoading, getData, accountInfo }) => { const [files, setFiles] = useState([]); const onDrop = useCallback( uploadedFiles => { uploadedFiles.forEach((file) => { console.log(file) new Compressor(file, { quality: 0.5, width: 500, height: 500, resize: "contain",function. success(result) { setFiles([...files, result]); console.log(result) }, error(err) { console.log(err.message); }, }); }) }, [files]); return(<a bunch of stuff here>); } Al usar el fragmento de código anterior, si uploadedFiles contiene más de un archivo, surge un problema al comprimir cada foto y agregarla al estado ( [files, setFiles] ). Solo se agregará una de las imágenes y las demás se perderán.
Pasé varias horas intentando volver a trabajar esta función de diferentes maneras y la mejor solución que se me ocurrió hasta ahora ha sido la siguiente:
function compressFile(file) { return new Promise((resolve, reject) => { new Compressor(file, { quality: 0.5, width: 500, height: 500, resize: "contain",function. success(result) { resolve(result) }, error(err) { console.log(err.message); reject(err) }, }); }); } function compressFiles(files) { return new Promise((resolve, reject) => { files.forEach((file) => { console.log(file) compressFile(file) .then(compFile => { console.log(compFile) setFiles([...files, compFile]); }) }) resolve() }) } const onDrop = useCallback( async acceptedFiles => { message.loading('Compressing Images...'); compressFiles(acceptedFiles) }, [files]);Desafortunadamente, esto todavía no funciona y me preguntaba si alguien podría explicarme dónde me estoy equivocando.
Esto debería ayudar:
const compressFiles = files => Promise.all( files.map(file => compressFile(file)) ) .then(compressedFiles => { console.log(compressedFiles); setFiles([...files, ...compressedFiles]); });setFiles([...files, compFile]); Cada vez que se ejecute esta línea, creará una matriz que comenzará con lo que hay en los files y agregará un nuevo archivo. Esto eliminará cualquier otro archivo que se haya creado desde que comenzó, porque la variable de files solo almacena lo que comenzó, no los cambios que haya realizado. Por lo tanto, deberá usar la versión de función de setFiles para asegurarse de tener siempre la última versión del estado:
setFiles(prev => [...prev, compFile]); Un par de otras recomendaciones. Primero, le sugiero que no establezca el estado varias veces en un bucle asíncrono. Esto dará como resultado que los archivos estén en un orden impredecible y hará que el componente represente cada paso a lo largo del camino. En su lugar, puede esperar hasta que se complete toda la compresión y luego establecer el estado una vez al final. Para esperar una serie de promesas, puede usar Promise.all. En segundo lugar, dado que ya hizo que compressFile devuelva una promesa, no necesita usar el new Promise nuevamente en compressFiles . Poniendo estos juntos recomiendo:
function compressFiles(files) { const promises = files.map(file => compressFile(file)); Promise.all(promises).then(compressedFiles => { setFiles(prev => [...prev, ...compressedFiles]); }); }O usando async/await:
async function compressFiles(files) { const promises = files.map(file => compressFile(file)); const compressedFiles = await Promise.all(promises); setFiles(prev => [...prev, ...compressedFiles]); }