- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
围绕这个主题有几篇文章,但似乎没有一篇能完全解决我的问题。我尝试过使用几个不同的库,甚至是库的组合,以获得所需的结果。到目前为止,我运气不好,但感觉非常接近解决方案。
本质上,我想通过单击按钮下载 CSV 文件。我正在为按钮使用 Material-UI 组件,并希望尽可能保持功能与 React 紧密相关,仅在绝对必要时才使用 vanilla JS。
为了提供有关特定问题的更多背景信息,我有一份调查 list 。每个调查都有一定数量的问题,每个问题有 2-5 个答案。一旦不同的用户回答了调查,网站的管理员应该能够点击下载报告的按钮。该报告是一个 CSV 文件,其中包含与每个问题相关的标题和相应的数字,显示有多少人选择了每个答案。
显示下载 CSV 按钮的页面是一个列表。该列表显示有关每个调查的标题和信息。因此,该行中的每个调查都有自己的下载按钮。
每个调查都有一个与之关联的唯一 ID。此 ID 用于获取后端服务并提取相关数据(仅针对该调查),然后将其转换为适当的 CSV 格式。由于列表中可能包含数百个调查,因此每次单击相应调查的按钮时都应仅获取数据。
我曾尝试使用多个库,例如 CSVLink 和 json2csv。我的第一次尝试是使用 CSVLink。本质上,CSVLink 被隐藏并嵌入到按钮内部。单击按钮时,它会触发提取,从而提取必要的数据。然后更新组件的状态并下载 CSV 文件。
import React from 'react';
import Button from '@material-ui/core/Button';
import { withStyles } from '@material-ui/core/styles';
import { CSVLink } from 'react-csv';
import { getMockReport } from '../../../mocks/mockReport';
const styles = theme => ({
button: {
margin: theme.spacing.unit,
color: '#FFF !important',
},
});
class SurveyResults extends React.Component {
constructor(props) {
super(props);
this.state = { data: [] };
this.getSurveyReport = this.getSurveyReport.bind(this);
}
// Tried to check for state update in order to force re-render
shouldComponentUpdate(nextProps, nextState) {
return !(
(nextProps.surveyId === this.props.surveyId) &&
(nextState.data === this.state.data)
);
}
getSurveyReport(surveyId) {
// this is a mock, but getMockReport will essentially be making a fetch
const reportData = getMockReport(surveyId);
this.setState({ data: reportData });
}
render() {
return (<CSVLink
style={{ textDecoration: 'none' }}
data={this.state.data}
// I also tried adding the onClick event on the link itself
filename={'my-file.csv'}
target="_blank"
>
<Button
className={this.props.classes.button}
color="primary"
onClick={() => this.getSurveyReport(this.props.surveyId)}
size={'small'}
variant="raised"
>
Download Results
</Button>
</CSVLink>);
}
}
export default withStyles(styles)(SurveyResults);
我一直面临的问题是,在第二次单击按钮之前,状态不会正确更新。更糟糕的是,当 this.state.data 作为 prop 传递到 CSVLink 时,它始终是一个空数组。下载的 CSV 中未显示任何数据。最终,这似乎不是最好的方法。无论如何,我不喜欢为每个按钮设置一个隐藏组件的想法。
我一直在尝试使用 CSVDownload 组件让它工作。 (那个和 CSVLink 都在这个包中:https://www.npmjs.com/package/react-csv)
DownloadReport 组件呈现 Material-UI 按钮并处理事件。单击该按钮时,它会将事件传播几个级别直至有状态组件并更改 allowDownload 的状态。这反过来会触发 CSVDownload 组件的呈现,该组件进行提取以获取指定的调查数据并导致下载 CSV。
import React from 'react';
import Button from '@material-ui/core/Button';
import { withStyles } from '@material-ui/core/styles';
import DownloadCSV from 'Components/ListView/SurveyTable/DownloadCSV';
import { getMockReport } from '../../../mocks/mockReport';
const styles = theme => ({
button: {
margin: theme.spacing.unit,
color: '#FFF !important',
},
});
const getReportData = (surveyId) => {
const reportData = getMockReport(surveyId);
return reportData;
};
const DownloadReport = props => (
<div>
<Button
className={props.classes.button}
color="primary"
// downloadReport is defined in a stateful component several levels up
// on click of the button, the state of allowDownload is changed from false to true
// the state update in the higher component results in a re-render and the prop is passed down
// which makes the below If condition true and renders DownloadCSV
onClick={props.downloadReport}
size={'small'}
variant="raised"
>
Download Results
</Button>
<If condition={props.allowDownload}><DownloadCSV reportData={getReportData(this.props.surveyId)} target="_blank" /></If>
</div>);
export default withStyles(styles)(DownloadReport);
在此处呈现 CSV 下载:
import React from 'react';
import { CSVDownload } from 'react-csv';
// I also attempted to make this a stateful component
// then performed a fetch to get the survey data based on this.props.surveyId
const DownloadCSV = props => (
<CSVDownload
headers={props.reportData.headers}
data={props.reportData.data}
target="_blank"
// no way to specify the name of the file
/>);
export default DownloadCSV;
这里的一个问题是无法指定 CSV 的文件名。它似乎也不能每次都可靠地下载文件。事实上,它似乎只在第一次点击时执行。它似乎也没有提取数据。
我考虑过使用 json2csv 和 js-file-download 包的方法,但我希望避免使用 vanilla JS 并坚持只使用 React。这是一件好事吗?这两种方法中的一种似乎也应该起作用。有没有人以前解决过这样的问题并对解决它的最佳方法有明确的建议?
我很感激任何帮助。谢谢!
最佳答案
关于如何做到这一点有一个很好的答案 here在 react-csv
问题线程上。我们的代码库是用带有钩子(Hook)的“现代”风格编写的。以下是我们如何改编该示例:
import React, { useState, useRef } from 'react'
import { Button } from 'react-bootstrap'
import { CSVLink } from 'react-csv'
import api from 'services/api'
const MyComponent = () => {
const [transactionData, setTransactionData] = useState([])
const csvLink = useRef() // setup the ref that we'll use for the hidden CsvLink click once we've updated the data
const getTransactionData = async () => {
// 'api' just wraps axios with some setting specific to our app. the important thing here is that we use .then to capture the table response data, update the state, and then once we exit that operation we're going to click on the csv download link using the ref
await api.post('/api/get_transactions_table', { game_id: gameId })
.then((r) => setTransactionData(r.data))
.catch((e) => console.log(e))
csvLink.current.link.click()
}
// more code here
return (
// a bunch of other code here...
<div>
<Button onClick={getTransactionData}>Download transactions to csv</Button>
<CSVLink
data={transactionData}
filename='transactions.csv'
className='hidden'
ref={csvLink}
target='_blank'
/>
</div>
)
}
(我们使用 react bootstrap 而不是 material ui,但你会实现完全相同的想法)
关于javascript - ReactJS:单击按钮下载 CSV 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53504924/
这是关于非标准属性的。 https://facebook.github.io/react/docs/tags-and-attributes.html 在 react 中我做了这个: React.cr
我制作了 2 个组件:1)内容(使用 fetch() 显示数据)2)分页(共5页,每页16个对象) 我创建了 2 个状态变量,分别称为 start:0 和 end:16。现在,每当用户单击页码时,我都
我们正在使用 ReactJS 创建一个搜索前端。要求是当用户单击文档名称时,该文档必须在嵌入式查看器中打开。有人为此使用过任何 ReactJS 组件吗?否则,我应该使用 JQuery 查看器组件吗?请
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 1 年前。
我现有的项目: 前端框架 - PHP Codeigniter 和 PHP Laravel 后端框架 - JAVA Springboot 我正在尝试将前端框架更改为 ReactJS。我想知道与 Reac
我有一个实现刷新授权 token 的方案。在这种情况下,我为每种操作(发布、获取、删除)实现了一个通用操作,并使用参数调用它们。 export function Get(param) { return
我现在有 { _this.setState({startDate: input})}}/> 无论我一直在改变什么(onChange 部分到 ref 等等),当我 console.log 我的状态时,
我在两个不同的文件中有两个单独的组件 组件A 和 组件B 我在 中有一个按钮组件B 现在我想测试当 中的特定按钮时组件B 被点击,组件A 应呈现如下: import { render, screen,
我有一个包含几个问题的表格。一些问题有一组子问题。 这些是使用以下代码呈现的。 { Object.keys(this.props.moduleDetails.questions).map(
我有两个组件。第一个状态初始化: import React from 'react'; class One extends React.Component { constructor(prop
我的项目是一个对象数组,我只获取名称并在 3 in 3 的屏幕上渲染,使用“下一个”和“上一个”按钮更改名称,并且可以过滤字母。 我想要添加一个新值,在输入中键入并单击按钮添加。 我的代码按钮: ad
我有一个组件实例,应该从不同的地方更新。如何从其他几个组件中更新此组件的 props? class ParentComponent extends React.Component { ...
我想问,是否可以基于变量返回一个组件,我的想法是否可以: var location = this.props.location // Eg. Asia,Australia 我的问题是我需要单独手动导
有没有办法在渲染后立即选择要覆盖的文本?我的意思是选择 - 最佳答案 您可以尝试使用两种方法.focus和.select .focus() method sets focus on the speci
我渲染了以下内容: 这是事件处理程序: handleCompanySubmit(event) { console.log("company submit") e
作为ReactJS的初学者,我现在使用出色的ReactJS Datepicker。有关我的自定义日期格式的问题: 我没有找到任何文档来解释所有可能性,例如M是月份,MM是2个字母的月份,依此类推。(我
我创建了一个表并正在对其进行过滤,但是当我清除搜索查询时,表数据不会显示,并且表会卡在查询结果上。SearchBox 是文本框,TableData 是表格,在 Container 中我正在更改 Sea
我在表格设置中有图标,这样当单击图标时,会呈现不同的图标。现在这工作正常,但我想为我单击的行中的特定行重新呈现不同的图标,而不是在每一行中重新呈现不同的图标。不知道我将如何去做这件事。这是我的代码:
我正在尝试使用 React 构建一个简单的应用程序,它有两个组件,一个嵌入另一个组件。子组件是一个收缩的菜单,单击它时,它会展开。我希望能够在单击父元素或子元素失去焦点时重新收缩它。 这是父组件的样子
我需要知道 REACT JS 或 HTML5 中是否有任何 API 可以提供用户不活动时自动注销的功能。我的代码如下,我不知道出了什么问题,它给了我错误 startTimer 未定义和不必要的绑定(b
我是一名优秀的程序员,十分优秀!