如何在 ReactJs 中使用 dropzone 将文件及其描述添加到状态?
How to add a file and its description to the state using dropzone in ReactJs?
如何使用 select、使用 react-dropzone 将一个或多个文件及其描述添加到组件状态。
我正在使用 Reactjs、dropzone 和 bootstrap,我想要实现的是:添加一个或多个文件(通过将它们拖到一个区域),然后查看已添加文件的列表和 select 每个输入(带有供用户定义“类型”的选项)将所有这些保存在一个状态中,然后将该信息发送到 API。
类似于图像中显示的内容:
我目前的代码,returns 我接受的文件列表,取决于它们的扩展名(pdf、xlsx ...)和拒绝的文件,但我不知道如何添加 select(带有“类型”来自文件的选项,可以是“摘要”、“报告”、“测试”...)并将其保存在状态中,然后将其发送到 API.
我目前使用 react-dropzone 的代码是这样的:
const baseStyle = {
flex: 1,
display: "flex",
flexDirection: "column",
alignItems: "center",
padding: "20px",
borderWidth: 2,
borderRadius: 20,
borderColor: "#26C2E7",
borderStyle: "dashed",
backgroundColor: "#fafafa",
color: "#c4c4c4",
outline: "none",
transition: "border .24s ease-in-out"
};
const activeStyle = {
borderColor: "#f2f"
};
const acceptStyle = {
borderColor: "#f8f"
};
const rejectStyle = {
borderColor: "#f2f"
};
function InputFiles(props) {
const {
acceptedFiles,
fileRejections,
isDragActive,
isDragAccept,
isDragReject,
getRootProps,
getInputProps
} = reactDropzone.useDropzone({
accept: ".xlsx,.docx,.pdf"
});
const style = React.useMemo(
() => ({
...baseStyle,
...(isDragActive ? activeStyle : {}),
...(isDragAccept ? acceptStyle : {}),
...(isDragReject ? rejectStyle : {})
}),
[isDragActive, isDragReject, isDragAccept]
);
const acceptedFileItems = acceptedFiles.map((file) => (
<li key={file.path}>
{file.path} - {file.size} bytes
</li>
));
const fileRejectionItems = fileRejections.map(({ file, errors }) => (
<li key={file.path}>
{file.path} - {file.size} bytes
<ul>
{errors.map((e) => (
<li key={e.code}>{e.message}</li>
))}
</ul>
</li>
));
return (
<section className="container">
{/* <div {...getRootProps({ style })}> */}
<div {...getRootProps({ style })}>
<input {...getInputProps()} />
<p>Drag 'n' drop some files here, or click to select files</p>
<em>(Only *.pdf , *.xlsx , *.docx files will be accepted)</em>
</div>
<aside>
<h4>Accepted files</h4>
<ul>{acceptedFileItems}</ul>
<h4>Rejected files</h4>
<ul>{fileRejectionItems}</ul>
</aside>
</section>
);
}
ReactDOM.render(<InputFiles />, document.body);
window.onload = function() {
console.log('onload');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.7.2/prop-types.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.1/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dropzone/11.2.0/index.js"></script>
目标是得到这样的东西:
添加文件及其描述时,它们必须保存在组件的状态中,objective 单击保存时,会向 [=36= 发出 POST 请求],点击取消时,必须删除状态信息
useDropZone
使用回调 onDrop
可以让您像这样获取文件的名称:
const onDrop = React.useCallback((acceptedFiles) => {
// Do something with the files
}, []);
const { ... } = useDropzone({ onDrop });
每次删除文件时,一旦有了文件名,就可以将其存储在一个状态中,显示名称和 selects,并在每次 select 出现时相应地更新该状态点击了。
另请注意,doc 表示它应该至少是 React 16.8,但您似乎使用的是 React 16.6。
正如@Emmanuel 在他的回答中提到的那样,您可以将文件存储在一个状态中,此实现使用名称作为键将文件存储在映射中。
import React, { useMemo, useState } from "react";
import { useDropzone } from "react-dropzone";
const baseStyle = {
flex: 1,
display: "flex",
flexDirection: "column",
alignItems: "center",
padding: "20px",
borderWidth: 2,
borderRadius: 20,
borderColor: "#26C2E7",
borderStyle: "dashed",
backgroundColor: "#fafafa",
color: "#c4c4c4",
outline: "none",
transition: "border .24s ease-in-out"
};
const activeStyle = {
borderColor: "#f2f"
};
const acceptStyle = {
borderColor: "#f8f"
};
const rejectStyle = {
borderColor: "#f2f"
};
function InputFiles(props) {
const [files, setFiles] = useState({});
const {
fileRejections,
isDragActive,
isDragAccept,
isDragReject,
getRootProps,
getInputProps
} = useDropzone({
onDrop: (acceptedFiles) => {
setFiles((prevFiles) =>
acceptedFiles.reduce(
(acc, file) => ({
...acc,
[file.name]: {
file,
fileType: ""
}
}),
prevFiles
)
);
},
accept: ".xlsx,.docx,.pdf"
});
const style = useMemo(
() => ({
...baseStyle,
...(isDragActive ? activeStyle : {}),
...(isDragAccept ? acceptStyle : {}),
...(isDragReject ? rejectStyle : {})
}),
[isDragActive, isDragReject, isDragAccept]
);
const acceptedFileItems = Object.keys(files).map((fileName) => {
const currentFile = files[fileName].file;
const onSelectChange = (e) => {
e.persist();
setFiles((prevFiles) => {
return {
...prevFiles,
[fileName]: {
...prevFiles[fileName],
fileType: e.target.value
}
};
});
};
return (
<li key={fileName}>
<div style={{ display: "flex" }}>
<span>
{currentFile.path} - {currentFile.size} bytes
</span>
<select value={currentFile.fileType} onChange={onSelectChange}>
<option value=""></option>
<option value="summary">summary</option>
<option value="description">report</option>
<option value="report">description</option>
</select>
</div>
</li>
);
});
const fileRejectionItems = fileRejections.map(({ file, errors }) => (
<li key={file.path}>
{file.path} - {file.size} bytes
<ul>
{errors.map((e) => (
<li key={e.code}>{e.message}</li>
))}
</ul>
</li>
));
return (
<section className="container">
{/* <div {...getRootProps({ style })}> */}
<div {...getRootProps({ style })}>
<input {...getInputProps()} />
<p>Drag 'n' drop some files here, or click to select files</p>
<em>(Only *.pdf , *.xlsx , *.docx files will be accepted)</em>
</div>
<aside>
<h4>Accepted files</h4>
<ul>{acceptedFileItems}</ul>
<h4>Rejected files</h4>
<ul>{fileRejectionItems}</ul>
<button onClick={() => console.log(files)}>console log files</button>
</aside>
</section>
);
}
export default InputFiles;
你可以在这里查看它的工作情况https://codesandbox.io/s/react-drop-zone-select-vhc2l
如何使用 select、使用 react-dropzone 将一个或多个文件及其描述添加到组件状态。
我正在使用 Reactjs、dropzone 和 bootstrap,我想要实现的是:添加一个或多个文件(通过将它们拖到一个区域),然后查看已添加文件的列表和 select 每个输入(带有供用户定义“类型”的选项)将所有这些保存在一个状态中,然后将该信息发送到 API。
类似于图像中显示的内容:
我目前的代码,returns 我接受的文件列表,取决于它们的扩展名(pdf、xlsx ...)和拒绝的文件,但我不知道如何添加 select(带有“类型”来自文件的选项,可以是“摘要”、“报告”、“测试”...)并将其保存在状态中,然后将其发送到 API.
我目前使用 react-dropzone 的代码是这样的:
const baseStyle = {
flex: 1,
display: "flex",
flexDirection: "column",
alignItems: "center",
padding: "20px",
borderWidth: 2,
borderRadius: 20,
borderColor: "#26C2E7",
borderStyle: "dashed",
backgroundColor: "#fafafa",
color: "#c4c4c4",
outline: "none",
transition: "border .24s ease-in-out"
};
const activeStyle = {
borderColor: "#f2f"
};
const acceptStyle = {
borderColor: "#f8f"
};
const rejectStyle = {
borderColor: "#f2f"
};
function InputFiles(props) {
const {
acceptedFiles,
fileRejections,
isDragActive,
isDragAccept,
isDragReject,
getRootProps,
getInputProps
} = reactDropzone.useDropzone({
accept: ".xlsx,.docx,.pdf"
});
const style = React.useMemo(
() => ({
...baseStyle,
...(isDragActive ? activeStyle : {}),
...(isDragAccept ? acceptStyle : {}),
...(isDragReject ? rejectStyle : {})
}),
[isDragActive, isDragReject, isDragAccept]
);
const acceptedFileItems = acceptedFiles.map((file) => (
<li key={file.path}>
{file.path} - {file.size} bytes
</li>
));
const fileRejectionItems = fileRejections.map(({ file, errors }) => (
<li key={file.path}>
{file.path} - {file.size} bytes
<ul>
{errors.map((e) => (
<li key={e.code}>{e.message}</li>
))}
</ul>
</li>
));
return (
<section className="container">
{/* <div {...getRootProps({ style })}> */}
<div {...getRootProps({ style })}>
<input {...getInputProps()} />
<p>Drag 'n' drop some files here, or click to select files</p>
<em>(Only *.pdf , *.xlsx , *.docx files will be accepted)</em>
</div>
<aside>
<h4>Accepted files</h4>
<ul>{acceptedFileItems}</ul>
<h4>Rejected files</h4>
<ul>{fileRejectionItems}</ul>
</aside>
</section>
);
}
ReactDOM.render(<InputFiles />, document.body);
window.onload = function() {
console.log('onload');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.7.2/prop-types.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.1/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dropzone/11.2.0/index.js"></script>
目标是得到这样的东西:
添加文件及其描述时,它们必须保存在组件的状态中,objective 单击保存时,会向 [=36= 发出 POST 请求],点击取消时,必须删除状态信息
useDropZone
使用回调 onDrop
可以让您像这样获取文件的名称:
const onDrop = React.useCallback((acceptedFiles) => {
// Do something with the files
}, []);
const { ... } = useDropzone({ onDrop });
每次删除文件时,一旦有了文件名,就可以将其存储在一个状态中,显示名称和 selects,并在每次 select 出现时相应地更新该状态点击了。
另请注意,doc 表示它应该至少是 React 16.8,但您似乎使用的是 React 16.6。
正如@Emmanuel 在他的回答中提到的那样,您可以将文件存储在一个状态中,此实现使用名称作为键将文件存储在映射中。
import React, { useMemo, useState } from "react";
import { useDropzone } from "react-dropzone";
const baseStyle = {
flex: 1,
display: "flex",
flexDirection: "column",
alignItems: "center",
padding: "20px",
borderWidth: 2,
borderRadius: 20,
borderColor: "#26C2E7",
borderStyle: "dashed",
backgroundColor: "#fafafa",
color: "#c4c4c4",
outline: "none",
transition: "border .24s ease-in-out"
};
const activeStyle = {
borderColor: "#f2f"
};
const acceptStyle = {
borderColor: "#f8f"
};
const rejectStyle = {
borderColor: "#f2f"
};
function InputFiles(props) {
const [files, setFiles] = useState({});
const {
fileRejections,
isDragActive,
isDragAccept,
isDragReject,
getRootProps,
getInputProps
} = useDropzone({
onDrop: (acceptedFiles) => {
setFiles((prevFiles) =>
acceptedFiles.reduce(
(acc, file) => ({
...acc,
[file.name]: {
file,
fileType: ""
}
}),
prevFiles
)
);
},
accept: ".xlsx,.docx,.pdf"
});
const style = useMemo(
() => ({
...baseStyle,
...(isDragActive ? activeStyle : {}),
...(isDragAccept ? acceptStyle : {}),
...(isDragReject ? rejectStyle : {})
}),
[isDragActive, isDragReject, isDragAccept]
);
const acceptedFileItems = Object.keys(files).map((fileName) => {
const currentFile = files[fileName].file;
const onSelectChange = (e) => {
e.persist();
setFiles((prevFiles) => {
return {
...prevFiles,
[fileName]: {
...prevFiles[fileName],
fileType: e.target.value
}
};
});
};
return (
<li key={fileName}>
<div style={{ display: "flex" }}>
<span>
{currentFile.path} - {currentFile.size} bytes
</span>
<select value={currentFile.fileType} onChange={onSelectChange}>
<option value=""></option>
<option value="summary">summary</option>
<option value="description">report</option>
<option value="report">description</option>
</select>
</div>
</li>
);
});
const fileRejectionItems = fileRejections.map(({ file, errors }) => (
<li key={file.path}>
{file.path} - {file.size} bytes
<ul>
{errors.map((e) => (
<li key={e.code}>{e.message}</li>
))}
</ul>
</li>
));
return (
<section className="container">
{/* <div {...getRootProps({ style })}> */}
<div {...getRootProps({ style })}>
<input {...getInputProps()} />
<p>Drag 'n' drop some files here, or click to select files</p>
<em>(Only *.pdf , *.xlsx , *.docx files will be accepted)</em>
</div>
<aside>
<h4>Accepted files</h4>
<ul>{acceptedFileItems}</ul>
<h4>Rejected files</h4>
<ul>{fileRejectionItems}</ul>
<button onClick={() => console.log(files)}>console log files</button>
</aside>
</section>
);
}
export default InputFiles;
你可以在这里查看它的工作情况https://codesandbox.io/s/react-drop-zone-select-vhc2l