Reagieren Sie, dass der useReducer-Status nicht korrekt aktualisiert wird

Post a reply

Smilies
:) :( :oops: :chelo: :roll: :wink: :muza: :sorry: :angel: :read: *x) :clever:
View more smilies

BBCode is ON
[img] is ON
[flash] is OFF
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: Reagieren Sie, dass der useReducer-Status nicht korrekt aktualisiert wird

by Guest » 16 Jan 2025, 11:44

Ich stehe in React vor einer Herausforderung, bei der ich eine Reihe von Bildern nacheinander hochladen muss. Dafür habe ich eine Art Warteschlange erstellt, in der das Bild, wenn der Benutzer es auswählt, zur Warteschlange hinzugefügt wird und die Warteschlange es verarbeitet, indem sie das Bild auf s3 hochlädt und die hochgeladene URL und den aktualisierten Status zurückgibt. Hier ist der Code dafür:

Code: Select all

import { uploadToS3 } from '~/utils/s3Upload';
import { PPFInspectionImage } from '~/context/PPFInspectionContext';

type StatusCallback = (
status: PPFInspectionImage['uploadStatus'],
serverUrl?: string,
key?: string
) => void;

interface QueueItem {
image: PPFInspectionImage;
partId: number;
onStatusChange: StatusCallback;
}

export class UploadManager {
private static instance: UploadManager;
private uploadQueue: QueueItem[] = [];
private isProcessing = false;
private maxConcurrent = 2;
private token: string;

private constructor(token: string) {
this.token = token;
}

static getInstance(token: string): UploadManager {
if (!UploadManager.instance || UploadManager.instance.token !== token) {
UploadManager.instance = new UploadManager(token);
}
return UploadManager.instance;
}

addToQueue(image: PPFInspectionImage, partId: number, onStatusChange: StatusCallback) {
this.uploadQueue.push({ image, partId, onStatusChange });
this.processQueue();
}

private async processQueue() {
if (this.isProcessing) return;
this.isProcessing = true;

try {
while (this.uploadQueue.length > 0) {
const batch = this.uploadQueue.splice(0, this.maxConcurrent);
await Promise.all(batch.map((item) => this.uploadImage(item)));
}
} catch (error) {
console.error('Error processing queue:', error);
} finally {
this.isProcessing = false;
}
}

private async uploadImage({ image, partId, onStatusChange }: QueueItem) {
onStatusChange('uploading');

try {
const response = await uploadToS3({
uri: image.localUri,
token: this.token,
inspectionType: 'ppf',
});

const serverUrl = `https://${process.env.EXPO_PUBLIC_BUCKET_NAME}.s3.${process.env.EXPO_PUBLIC_BUCKET_REGION}.amazonaws.com/${process.env.EXPO_PUBLIC_PPF_FOLDER}/${response.fileName}`;

onStatusChange('completed', serverUrl, response.key);
} catch (error) {
console.error('Upload failed:', error);
onStatusChange('failed');

// Add back to queue if retries remaining
if ((image.retryCount || 0) < 3) {
this.uploadQueue.push({
image: { ...image, retryCount: (image.retryCount || 0) + 1 },
partId,
onStatusChange,
});
}
}
}

// Method to retry failed uploads
retryUpload(image: PPFInspectionImage, partId: number, onStatusChange: StatusCallback) {
this.addToQueue({ ...image, retryCount: 0 }, partId, onStatusChange);
}
}
Jetzt möchte ich den Status aktualisieren, nachdem diese Warteschlange mit der Verarbeitung des Bildes fertig ist, für das ich den StatusCallback habe, und in diesem Status-Callback rufe ich eine useReducer-Aktion auf so

Code: Select all

// Start background upload
UploadManager.getInstance(token).addToQueue(newImage, partId, (status, serverUrl, key) => {
dispatch({
type: 'UPDATE_IMAGE_STATUS',
payload: { partId, id: newImage.id, status, serverUrl, key },
});
});
Das Problem besteht darin, dass die Bilder korrekt verarbeitet werden, wenn ich sie langsam hinzufüge. Der Status wird auch korrekt aktualisiert, aber wenn ich die Bilder schnell nacheinander hinzufüge, verarbeitet die Warteschlange sie, lädt sie hoch und gibt die korrekten vollständigen Status zurück. Wenn der Status jedoch mehrmals aktualisiert wird, wird der Status manchmal nicht richtig eingerichtet, was dazu führt, dass Der Status von ein oder zwei Bildern ist noch auf „Hochladen“ oder „Ausstehend“ eingestellt, aber in Wirklichkeit wurden sie erfolgreich hochgeladen.
Hier ist meine Reduzierung:

Code: Select all

case 'UPDATE_IMAGE_STATUS': {
const part = state.faults[action.payload.partId];
if (!part) return state;

return {
...state,
faults: {
...state.faults,
[action.payload.partId]: {
...part,
images: part.images.map((img) =>
img.id === action.payload.id
? {
...img,
uploadStatus: action.payload.status,
serverUrl: action.payload.serverUrl,
key: action.payload.key,
}
: img
),
},
},
};
}

Top