Я сейчас создаю форму в React.Желаемое поведение - отправка нескольких текстовых полей и одного или нескольких изображений, причем текстовые поля отправляются в конечную точку API, а изображения отправляются в корзину AWS S3.Здесь я свободно использую термин «форма», так как это два разных действия, только текстовые поля являются частью собственно HTML-формы, но отправка изображения будет инициирована одной и той же кнопкой.
Всеэто прекрасно работает с любыми данными текстового поля и тестированием отправки S3 в изоляции.Однако у меня возникают проблемы с правильной обработкой изображений на моем клиенте.
Для раздела формы «Добавить изображение» я использую реагировать-dropzone в дочернем компоненте.Вот этот дочерний компонент:
const Dropzone = (props) => {
const { classes, receiveLogin, switchScreen, addFormImages, loginReducer, screenReducer, imageFormReducer } = props;
const [files, setFiles] = useState([]);
const {getRootProps, getInputProps} = useDropzone({
accept: 'image/*',
onDrop: acceptedFiles => {
const _fileProperties = [
'lastModified',
'lastModifiedDate',
'name',
'path',
'preview',
'size',
'type',
'webkitRelativePath'
];
let newState = files.concat(acceptedFiles.map(file => Object.assign(file, {
preview: URL.createObjectURL(file)
})));
setFiles(newState);
console.log('newState in onDrop: ',newState);
// console.log('Array.isArray(newState) in onDrop: ',Array.isArray(newState));
const reader = new FileReader();
let reduxArr = [];
for (let i in newState) {
// PUSH SOMETHING HERE
reduxArr.push(SOMETHING);
}
addFormImages(reduxArr);
}
});
const Delete = (file) => {
const updatedFiles = files.filter(f => f.preview !== file.preview);
setFiles(updatedFiles);
addFormImages(updatedFiles);
}
const thumbs = files.map(file => (
<div className={classes.thumb} key={file.name}>
<DeleteIcon className={classes.delete} onClick={() => Delete(file)}/>
<div className={classes.thumbInner}>
<img
src={file.preview}
className={classes.img}
/>
</div>
</div>
));
useEffect(() => () => {
// Make sure to revoke the data uris to avoid memory leaks
files.forEach(file => URL.revokeObjectURL(file.preview));
}, [files]);
return (
<section>
<Grid container className={classes.fileUploadGrid}>
<Grid item xs>
<Grid
container
direction="column"
alignItems="center"
>
<div {...getRootProps()}>
<input {...getInputProps()} />
<Button variant="raised" component="span" className={classes.uploadButton}>
Add Pictures
<AddPhotoAlternateIcon />
</Button>
</div>
</Grid>
</Grid>
</Grid>
<Grid container className={classes.fileUploadGrid}>
<Grid item xs>
<Grid
container
direction="column"
alignItems="center"
>
<aside className={classes.thumbsContainer}>
{thumbs}
</aside>
</Grid>
</Grid>
</Grid>
</section>
);
}
addFormImages
- это действие Redux, которое будет принимать массив изображений.
Если в цикле for
я нажимаю newState[i]
на reduxArr
я получаю ошибку Objects are not valid as a React child (found: [object File]). If you meant to render a collection of children, use an array instead
.Я попытался использовать ответы на этот вопрос , которые советуют использовать FileReader
несколькими способами, но я все еще получаю ошибки.
Я пытался напрямую использовать код издочерний компонент в родительском компоненте в попытке обойти использование хранилища Redux, но поскольку react-dropzone
использует хуки внутри, я получаю ошибку Hooks can only be called inside the body of a function component
.
Как я могу делать то, что мне нужно делать?