#reactjs #react-dropzone
#reactjs #react-dropzone
Вопрос:
Я использую react-dropzone в своем приложении и хотел бы иметь несколько зон доступа на одной странице для предварительного просмотра нескольких изображений. Например, я хотел бы иметь возможность поместить изображение героя в выпадающую зону, которая отображает изображение героя в верхней части страницы. Затем я хотел бы поместить другое изображение в другую выпадающую зону, которая отображает изображение в контейнере эскизов.
import React, { useState, useMemo, useEffect } from "react";
import Container from "../components/Container";
import { useDropzone } from "react-dropzone";
const Test = () => {
// Dropzone
const baseStyle = {
flex: 1,
display: "flex",
flexDirection: "column",
alignItems: "center",
padding: "20px",
borderWidth: 2,
borderRadius: 2,
borderColor: "#eeeeee",
borderStyle: "dashed",
backgroundColor: "#fafafa",
color: "#bdbdbd",
outline: "none",
transition: "border .24s ease-in-out",
};
const activeStyle = {
borderColor: "#2196f3",
};
const acceptStyle = {
borderColor: "#00e676",
};
const rejectStyle = {
borderColor: "#ff1744",
};
const [files, setFiles] = useState({});
const { getRootProps, getInputProps, isDragActive, isDragAccept, isDragReject } = useDropzone({
accept: "image/*",
onDrop: (acceptedFiles) => {
console.log(acceptedFiles);
setFiles(
Object.assign(acceptedFiles[0], {
preview: URL.createObjectURL(acceptedFiles[0]),
})
);
},
});
const style = useMemo(
() => ({
...baseStyle,
...(isDragActive ? activeStyle : {}),
...(isDragAccept ? acceptStyle : {}),
...(isDragReject ? rejectStyle : {}),
}),
[isDragActive, isDragReject, isDragAccept]
);
useEffect(
() => () => {
// Make sure to revoke the data uris to avoid memory leaks
URL.revokeObjectURL(files.preview);
},
[files]
);
return (
<Container>
{/* This would be the dropzone for the Hero image */}
<div>
<div {...getRootProps({ style })}>
<input {...getInputProps()} />
<span style={{ fontSize: ".8rem" }}>Drop hero image here, or click to select file</span>
</div>
</div>
{/* This would be the dropzone for the Thumbnail image */}
<div>
<div {...getRootProps({ style })}>
<input {...getInputProps()} />
<span style={{ fontSize: ".8rem" }}>Drop hero image here, or click to select file</span>
</div>
</div>
{/* This would be where the Hero image is displayed */}
<img
style={{ width: "600px", height: "200px", margin: "0", display: "block" }}
src={files.preview ? files.preview : "https://via.placeholder.com/600x200"}
alt="Hero Image"
/>
{/* This would be where the Thumbnail image is displayed */}
<img
style={{ width: "600px", height: "200px", margin: "0", display: "block" }}
src={files.preview ? files.preview : "https://via.placeholder.com/600x200"}
alt="Thumbnail Image"
/>
</Container>
);
};
export default Test;
Я предполагаю, что мне нужно изменить функцию onDrop, но я не могу понять, как это сделать. Любая помощь будет с благодарностью!
Ответ №1:
-
Создайте две отдельные файловые переменные и обрабатывайте их отдельно.
-
используйте два отдельных getRootsProps и getInputProps для обоих входов.
const [file, setFile] = useState({}); const [fileGallery, setFileGallery] = useState({}); const { getRootProps:getRootfileProps, getInputProps:getInputfileProps } = useDropzone({ accept: 'image/*', onDrop: (acceptedFile) => { setFile( Object.assign(acceptedFile[0], { preview: URL.createObjectURL(acceptedFile[0]), }), ); }, }); const { getRootProps:getRootGalleryProps, getInputProps:getInputGalleryProps } = useDropzone({ accept: 'image/*', onDrop: (acceptedFile) => { setFileGallery( Object.assign(acceptedFile[0], { preview: URL.createObjectURL(acceptedFile[0]), }), ); }, }); return ( <Container> {/* This would be the dropzone for the Hero image */} <div> <div {...getRootfileProps({ style })}> <input {...getInputfileProps()} /> <span style={{ fontSize: ".8rem" }}>Drop hero image here, or click to select file</span> </div> </div> {/* This would be the dropzone for the Thumbnail image */} <div> <div {...getRootGalleryProps({ style })}> <input {...getInputGalleryProps()} /> <span style={{ fontSize: ".8rem" }}>Drop hero image here, or click to select file</span> </div> </div> {/* This would be where the Hero image is displayed */} <img style={{ width: "600px", height: "200px", margin: "0", display: "block" }} src={files.preview ? files.preview : "https://via.placeholder.com/600x200"} alt="Hero Image" /> {/* This would be where the Thumbnail image is displayed */} <img style={{ width: "600px", height: "200px", margin: "0", display: "block" }} src={files.preview ? files.preview : "https://via.placeholder.com/600x200"} alt="Thumbnail Image" /> </Container> ); }; export default Test;
Ответ №2:
вам нужно создать две отдельные файловые переменные и обрабатывать их отдельно. также вы используете одни и те же getRootsProps и getInputProps для обоих входов, что неверно.
const [file, setFile] = useState({});
const [fileGallery, setFileGallery] = useState({});
const { getRootProps:getRootfileProps, getInputProps:getInputfileProps } = useDropzone({
accept: 'image/*',
onDrop: (acceptedFile) => {
setFile(
Object.assign(acceptedFile[0], {
preview: URL.createObjectURL(acceptedFile[0]),
}),
);
},
});
const { getRootProps:getRootGalleryProps, getInputProps:getInputGalleryProps } = useDropzone({
accept: 'image/*',
onDrop: (acceptedFile) => {
setFileGallery(
Object.assign(acceptedFile[0], {
preview: URL.createObjectURL(acceptedFile[0]),
}),
);
},
});
Ответ №3:
Вы должны использовать два отдельных имени файлов в состоянии одно для героя одно для миниатюры и управлять каждым из них для каждой выпадающей зоны примерно так:
const [heroFiles, setHeroFiles] = useState({});
const [filesThumb, setFilesThumb] = useState({});
Ответ №4:
вы используете перехват Dropzone, и это затруднит достижение того, к чему вы стремитесь, вместо этого используйте компонент Dropzone и объявляйте состояние для каждого ввода Dropzone, который вы собираетесь использовать.
import React, { useState } from "react";
import Container from "../components/Container";
import Dropzone from "react-dropzone";
const Test = () => {
const [heroFiles, setHeroFiles] = useState([]);
const [thumbnailFiles, setThumbnailFiles] = useState([]);
return (
<Container>
{/* This would be the dropzone for the Hero image */}
<Dropzone onDrop={(acceptedFiles) => {
setHeroFiles(acceptedFiles.map(file => Object.assign(file, {
preview: URL.createObjectURL(file)
})));
}} name="heroImage" multiple={false}>
{({getRootProps, getInputProps}) => (
<div {...getRootProps({className: 'dropzone'})}>
<input {...getInputProps()} />
<span style={{ fontSize: ".8rem" }}>
Drop hero image here, or click to select file
</span>
</div>
)}
</Dropzone>
{/* This would be the dropzone for the Thumbnail image */}
<Dropzone onDrop={(acceptedFiles) => {
setHeroFiles(acceptedFiles.map(file => Object.assign(file, {
preview: URL.createObjectURL(file)
})));
}} name="heroImage" multiple={false}>
{({getRootProps, getInputProps}) => (
<div {...getRootProps({className: 'dropzone'})}>
<input {...getInputProps()} />
<span style={{ fontSize: ".8rem" }}>
Drop hero image here, or click to select file
</span>
</div>
)}
</Dropzone>
{/* This would be where the Hero image is displayed */}
<img style={{ width: "600px", height: "200px", margin: "0", display: "block" }} src={heroFiles.length > 0 ? heroFiles[0].preview : "https://via.placeholder.com/600x200"} alt="Hero Image"/>
{/* This would be where the Thumbnail image is displayed */}
<img style={{ width: "600px", height: "200px", margin: "0", display: "block" }} src={thumbnailFiles.length > 0 ? thumbnailFiles[0].preview : "https://via.placeholder.com/600x200"} alt="Thumbnail Image"/>
</Container>
);
}
export default Test;
предполагается, что это решит ваши проблемы.