Checkpoint: Résolution du problème de latence d'affichage avec double requestAnimationFrame : cette technique garantit que le navigateur peint l'animation à l'écran avant de bloquer sur le fetch. Le premier requestAnimationFrame permet à React de mettre à jour l'état, le second force le navigateur à afficher visuellement l'animation avant de démarrer l'upload. Déployé sur le VPS de production.
This commit is contained in:
@@ -196,53 +196,54 @@ function UploadAttestationDialog({
|
||||
return;
|
||||
}
|
||||
|
||||
// Forcer le rendu synchrone de l'interface AVANT de démarrer l'upload
|
||||
flushSync(() => {
|
||||
setUploading(true);
|
||||
setUploadProgress(0);
|
||||
});
|
||||
// Afficher immédiatement l'état de chargement
|
||||
setUploading(true);
|
||||
setUploadProgress(0);
|
||||
|
||||
// Démarrer l'upload de manière asynchrone
|
||||
(async () => {
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
// Utiliser requestAnimationFrame pour garantir que le navigateur
|
||||
// affiche l'animation AVANT de bloquer sur le fetch
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(async () => {
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
const progressInterval = setInterval(() => {
|
||||
setUploadProgress(prev => {
|
||||
if (prev >= 90) return prev;
|
||||
return prev + 10;
|
||||
});
|
||||
}, 200);
|
||||
const progressInterval = setInterval(() => {
|
||||
setUploadProgress(prev => {
|
||||
if (prev >= 90) return prev;
|
||||
return prev + 10;
|
||||
});
|
||||
}, 200);
|
||||
|
||||
const response = await fetch('/api/upload-file', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
});
|
||||
const response = await fetch('/api/upload-file', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
});
|
||||
|
||||
clearInterval(progressInterval);
|
||||
setUploadProgress(100);
|
||||
clearInterval(progressInterval);
|
||||
setUploadProgress(100);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Erreur lors de l\'upload');
|
||||
}
|
||||
if (!response.ok) {
|
||||
throw new Error('Erreur lors de l\'upload');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
setFileData({
|
||||
nomFichier: file.name,
|
||||
urlFichier: data.url,
|
||||
s3Key: data.key,
|
||||
typeFichier: file.type,
|
||||
tailleFichier: file.size,
|
||||
});
|
||||
toast.success('Fichier uploadé avec succès');
|
||||
} catch (error) {
|
||||
toast.error('Erreur lors de l\'upload du fichier');
|
||||
setUploadProgress(0);
|
||||
} finally {
|
||||
setUploading(false);
|
||||
}
|
||||
})(); // Fermer et exécuter la fonction async
|
||||
const data = await response.json();
|
||||
setFileData({
|
||||
nomFichier: file.name,
|
||||
urlFichier: data.url,
|
||||
s3Key: data.key,
|
||||
typeFichier: file.type,
|
||||
tailleFichier: file.size,
|
||||
});
|
||||
toast.success('Fichier uploadé avec succès');
|
||||
} catch (error) {
|
||||
toast.error('Erreur lors de l\'upload du fichier');
|
||||
setUploadProgress(0);
|
||||
} finally {
|
||||
setUploading(false);
|
||||
}
|
||||
}); // Fermer requestAnimationFrame interne
|
||||
}); // Fermer requestAnimationFrame externe
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
|
||||
Reference in New Issue
Block a user