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:
Manus
2026-01-30 09:37:18 -05:00
parent 1bbbe842b5
commit e68949baeb
2 changed files with 44 additions and 41 deletions

View File

@@ -196,53 +196,54 @@ function UploadAttestationDialog({
return; return;
} }
// Forcer le rendu synchrone de l'interface AVANT de démarrer l'upload // Afficher immédiatement l'état de chargement
flushSync(() => { setUploading(true);
setUploading(true); setUploadProgress(0);
setUploadProgress(0);
});
// Démarrer l'upload de manière asynchrone // Utiliser requestAnimationFrame pour garantir que le navigateur
(async () => { // affiche l'animation AVANT de bloquer sur le fetch
try { requestAnimationFrame(() => {
const formData = new FormData(); requestAnimationFrame(async () => {
formData.append('file', file); try {
const formData = new FormData();
formData.append('file', file);
const progressInterval = setInterval(() => { const progressInterval = setInterval(() => {
setUploadProgress(prev => { setUploadProgress(prev => {
if (prev >= 90) return prev; if (prev >= 90) return prev;
return prev + 10; return prev + 10;
}); });
}, 200); }, 200);
const response = await fetch('/api/upload-file', { const response = await fetch('/api/upload-file', {
method: 'POST', method: 'POST',
body: formData, body: formData,
}); });
clearInterval(progressInterval); clearInterval(progressInterval);
setUploadProgress(100); setUploadProgress(100);
if (!response.ok) { if (!response.ok) {
throw new Error('Erreur lors de l\'upload'); throw new Error('Erreur lors de l\'upload');
} }
const data = await response.json(); const data = await response.json();
setFileData({ setFileData({
nomFichier: file.name, nomFichier: file.name,
urlFichier: data.url, urlFichier: data.url,
s3Key: data.key, s3Key: data.key,
typeFichier: file.type, typeFichier: file.type,
tailleFichier: file.size, tailleFichier: file.size,
}); });
toast.success('Fichier uploadé avec succès'); toast.success('Fichier uploadé avec succès');
} catch (error) { } catch (error) {
toast.error('Erreur lors de l\'upload du fichier'); toast.error('Erreur lors de l\'upload du fichier');
setUploadProgress(0); setUploadProgress(0);
} finally { } finally {
setUploading(false); setUploading(false);
} }
})(); // Fermer et exécuter la fonction async }); // Fermer requestAnimationFrame interne
}); // Fermer requestAnimationFrame externe
}} }}
/> />
</label> </label>

View File

@@ -1476,3 +1476,5 @@
- [x] Corriger la latence d'affichage du message d'upload (forcer le rendu avant traitement) - [x] Corriger la latence d'affichage du message d'upload (forcer le rendu avant traitement)
- [x] Restructurer le flux d'upload avec useEffect pour affichage immédiat - [x] Restructurer le flux d'upload avec useEffect pour affichage immédiat
- [x] Corriger la latence avec requestAnimationFrame pour affichage avant fetch bloquant