Я столкнулся с проблемой в React: мне нужно загрузить несколько изображений одно за другим. Для этого я создал своего рода очередь, в которой, когда пользователь выбирает изображение, оно добавляется в очередь, и очередь обрабатывает его, загружая изображение в s3, и возвращает загруженный URL-адрес и обновленный статус. Вот код для этого:
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);
}
}
теперь дело в том, что я хочу обновить состояние после того, как эта очередь завершит обработку изображения, для которого у меня есть statusCallback, и в этом обратном вызове состояния я вызываю действие useReducer вот так
// 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 },
});
});
Проблема в том, что если я добавляю изображения медленно, они обрабатываются правильно. Состояние также обновляется правильно, но когда я быстро добавляю изображения одно за другим, очередь обрабатывает их, загружает и возвращает правильные полные статусы, но когда состояние обновляется несколько раз, иногда статус не устанавливается правильно, что приводит к статус одного или двух изображений все еще установлен на загрузку или ожидание, но на самом деле они загружены успешно.
вот мой редуктор:
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
),
},
},
};
}
Подробнее здесь: https://stackoverflow.com/questions/793 ... -correctly
Состояние реакции useReducer не обновляется правильно ⇐ Javascript
Форум по Javascript
-
Anonymous
1737024272
Anonymous
Я столкнулся с проблемой в React: мне нужно загрузить несколько изображений одно за другим. Для этого я создал своего рода очередь, в которой, когда пользователь выбирает изображение, оно добавляется в очередь, и очередь обрабатывает его, загружая изображение в s3, и возвращает загруженный URL-адрес и обновленный статус. Вот код для этого:
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);
}
}
теперь дело в том, что я хочу обновить состояние после того, как эта очередь завершит обработку изображения, для которого у меня есть statusCallback, и в этом обратном вызове состояния я вызываю действие useReducer вот так
// 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 },
});
});
Проблема в том, что если я добавляю изображения медленно, они обрабатываются правильно. Состояние также обновляется правильно, но когда я быстро добавляю изображения одно за другим, очередь обрабатывает их, загружает и возвращает правильные полные статусы, но когда состояние обновляется несколько раз, иногда статус не устанавливается правильно, что приводит к статус одного или двух изображений все еще установлен на загрузку или ожидание, но на самом деле они загружены успешно.
вот мой редуктор:
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
),
},
},
};
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79361248/react-usereducer-state-not-updating-correctly[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия