reactjs - React- Button Onclick 不从文件系统渲染文件 - 在任何点击链接时它总是从文件对象渲染最后一个文件
问题描述
我对 React 比较陌生,当然在这个项目中我缺少一些基本的东西。
我在此处的代码和框中上传了一个具有此功能的小示例项目。虽然您会在代码和框中看到错误(因为目前不认为它支持 node 和 mongo 后端)。将代码推送到那里只是为了显示整个项目。
这是项目流程。
它是一个全栈项目,我在 /uploads 目录中使用 node 和 mongodb 将几个文件上传到项目的文件系统。但是,我当前的问题仅在 React 前端,即通过单击按钮呈现上传的文件。在 React 前端,我通过单击按钮然后打开 Material-UI 模式来呈现这些文件。因此,每次用户单击“下载文件”时,都会打开一个模态,在该模态中我单击“查看文件”按钮,相关文件应在新选项卡中呈现。但是每次我单击视图文件时,确实会渲染一个上传的文件,但它始终是“图像”对象中的最后一个文件。
这是我../src/Components/FileUpload.js
实现的 Material-UI 模式。handleClose 函数接受一个参数fileLink
,它是我从images
对象中获取的文件的链接。
class FileUpload extends Component {
state = {
documents: [],
open: false
};
handleClickOpen = () => {
this.setState({ open: true });
};
handleClose = fileLink => {
this.setState({
open: false
});
window.open(`${fileLink}`, "_blank");
};
deleteDocument = id => {
axios.delete("/api/document/" + id).then(() => {
this.setState({
documents: this.state.documents.filter(document => document._id !== id)
});
});
};
componentDidMount() {
axios.get("/api/document").then(res => {
this.setState({ documents: res.data });
});
}
importAll = result => {
let images = {};
result.keys().map((item, index) => {
return (images[item.replace("./", "")] = result(item));
});
return images;
};
render() {
const webpackContext = require.context(
"../../uploads",
false,
/\.(png|jpe?g|svg|pdf|doc|odt)$/
);
const images = this.importAll(webpackContext);
console.log(images);
return (
<div className="bg-success">
<Col xs="8">
<Card>
<CardHeader className="p-2 mb-2 bg-primary text-white" />
<CardBody>
<CardText>
<table className="table table-stripe">
<thead>
<tr>
<th>Document Id</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{this.state.documents.map(document => (
<tr>
<td>{document.document_id}</td>
<td>{document.description}</td>
<td>
<Button onClick={this.handleClickOpen}>
Download file
</Button>
<Dialog
open={this.state.open}
onClose={this.handleClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">
Required Information
</DialogTitle>
<DialogContent>
<DialogContentText>
Update these info to download the file
</DialogContentText>
<TextField
autoFocus
margin="dense"
id="name"
label="Email Address"
type="email"
fullWidth
/>
</DialogContent>
<DialogActions>
<Button
onClick={this.handleClose}
color="primary"
>
Cancel
</Button>
<Button
onClick={this.handleClose.bind(
this,
images[`${document.path}`]
)}
color="primary"
>
Download file
</Button>
</DialogActions>
</Dialog>
</td>
<td>
<Link
to={`/api/document/edit/${document._id}`}
class="btn btn-success"
>
Edit Description
</Link>
</td>
<td>
<button
onClick={this.deleteDocument.bind(
this,
document._id
)}
className="btn btn-danger"
>
Delete
</button>
</td>
</tr>
))}
</tbody>
</table>
</CardText>
</CardBody>
</Card>
</Col>
```
所以,点击按钮我正在做一个
onClick={this.handleClose.bind}
handleClose
将文件路径链接的参数传递给函数(即我应该能够呈现该文件的链接)
我正在使用 Webpack 的 require.context 从我在此组件中创建的对象中获取文件链接,并将其保存在名为images的变量中
const images = this.importAll(webpackContext);
但是每次我单击视图文件时,确实会渲染一个上传的文件,但它始终是“图像”对象中的最后一个文件。
该handleClose
函数不拾取图像对象中的其他文件。
解决方案
回答我自己的问题(以防它帮助其他人) -
我犯的错误是这样的——
当将数据从我FileUpload.js
.map
的函数传递到handleClose
传递 fileLink 进行渲染的函数时,我没有实现任何方法来挂钩到链接引用的那个特定文件。由 A) 从 FileUpload.js 单击按钮下载/查看文件时更正,现在我正在渲染一个全新的组件 ( RenderFile.js
),它将负责打开 Material-UI 模式并渲染正确的链接以查看文件.
这是我更新的 FileUpload.js 文件
class FileUpload extends Component {
state = {
documents: [],
clicked: false,
textBeforeDownload: "View/Download"
};
launchRenderFileComp = () => {
this.setState({
clicked: true,
textBeforeDownload: ""
});
};
deleteDocument = id => {
axios.delete("/api/document/" + id).then(() => {
this.setState({
documents: this.state.documents.filter(document => document._id !== id)
});
});
};
componentDidMount() {
axios.get("/api/document").then(res => {
this.setState({ documents: res.data });
});
}
importAll = result => {
let images = {};
result.keys().map((item, index) => {
return (images[item.replace("./", "")] = result(item));
});
return images;
};
render() {
const { documents } = this.state;
const webpackContext = require.context(
"../../uploads",
false,
/\.(png|jpe?g|svg|pdf|doc|odt)$/
);
const images = this.importAll(webpackContext);
return (
<div className="bg-success">
<Col xs="8">
<Card>
<CardHeader className="p-2 mb-2 bg-primary text-white" />
<CardBody>
<CardText>
<table className="table table-stripe">
<thead>
<tr>
<th>Document Id</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{documents.map(document => (
<tr>
<td>{document.document_id}</td>
<td>{document.description}</td>
<td>
<Button onClick={this.launchRenderFileComp}>
{this.state.clicked ? (
<RenderFile linkForRender={document.path} />
) : null}
{this.state.textBeforeDownload}
</Button>
</td>
<td>
<Link
to={`/api/document/edit/${document._id}`}
class="btn btn-success"
>
Edit Description
</Link>
</td>
<td>
<button
onClick={this.deleteDocument.bind(
this,
document._id
)}
className="btn btn-danger"
>
Delete
</button>
</td>
</tr>
))}
</tbody>
</table>
</CardText>
</CardBody>
</Card>
</Col>
这是新的 RenderFile.js 组件,它将负责打开模式和渲染文件。
import React, { Component } from "react";
import Button from "@material-ui/core/Button";
import TextField from "@material-ui/core/TextField";
import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import DialogContentText from "@material-ui/core/DialogContentText";
import DialogTitle from "@material-ui/core/DialogTitle";
class RenderFile extends Component {
state = {
open: false
};
handleToggle = () => {
this.setState({
open: !this.state.open
});
};
handleClickOpen = () => {
this.setState({ open: true });
};
handleClose = file => {
// file = this.file;
this.setState({
open: false
});
window.open(`${file}`, "_blank");
};
handleCancel = () => {
this.setState({ open: false });
};
importAll = result => {
let images = {};
result.keys().map((item, index) => {
return (images[item.replace("./", "")] = result(item));
});
return images;
};
render() {
const webpackContext = require.context(
"../../uploads",
false,
/\.(png|jpe?g|svg|pdf|doc|odt)$/
);
const images = this.importAll(webpackContext);
const { linkForRender } = this.props;
return (
<div>
<Button onClick={this.handleClickOpen}>Click to View File</Button>
<Dialog
open={this.state.open}
onClose={this.handleToggle}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">Required Information</DialogTitle>
<DialogContent>
<DialogContentText>
Update these info to download the file
</DialogContentText>
<TextField
autoFocus
margin="dense"
id="name"
label="Email Address"
type="email"
fullWidth
/>
</DialogContent>
<DialogActions>
<Button onClick={this.handleCancel} color="primary">
Cancel
</Button>
<Button
onClick={this.handleClose.bind(this, images[`${linkForRender}`])}
color="primary"
>
View or Download File
</Button>
</DialogActions>
</Dialog>
</div>
);
}
}
推荐阅读
- nginx - 可以在 nginx 配置中的 add_header 中放置换行符吗?
- azure - 针对间隔自定义事件的 Azure 警报
- mysql - 如何将现有表设置修改为自动增加 PK 字段?
- c++ - 在 Rcpp 中将 boost::array 转换为 NumericVector
- angular - 我的表单材料需要选择2次
- ios - 接收到的 json 数据为 531 字节,在 swift 4.1 和 Xcode 9.2 中出现 curruptedData 错误
- javascript - Javascript 'yyyy-mm-dd hh:mm:ss' 到时间戳
- pyspark - 如果 csv 上没有标题,则在 pyspark 中读取 CSV
- string - 如何在powershell中删除部分字符串?
- html - 用于不同表单/方法的 HTML 1 输入文本