[英]React: Button to export data from Firebase Firestore database
I am trying to make a button in my React web application which exports either all data or preferably specific collections from Firebase Cloud Firestore database as JSON.我正在尝试在我的 React web 应用程序中制作一个按钮,该按钮将所有数据或最好是特定的 collections 从 Firebase Cloud Firestore 数据库导出为 JSON。
Below is what I'm working with currently.以下是我目前正在处理的内容。 This sort of works but not properly.这种工作但不正确。 When I click the button and download the JSON, it will be empty because the data wasn't loaded yet.当我单击按钮并下载 JSON 时,它会是空的,因为尚未加载数据。 When I click the button the second time and download the JSON again, it will have the desired data because it was loaded after the first click.当我第二次单击该按钮并再次下载 JSON 时,它将具有所需的数据,因为它是在第一次单击后加载的。 I have tried different async and Promise structures to wait for all the data before starting the download but so far I have failed.在开始下载之前,我尝试了不同的异步和 Promise 结构来等待所有数据,但到目前为止我都失败了。 The data could always be downloaded pre-hand with useEffect but this is not an option because it extremely increases the Firebase calls made with the application.数据总是可以使用 useEffect 预先下载,但这不是一个选项,因为它极大地增加了应用程序的 Firebase 调用。
How do you properly wait for all the data before downloading it?在下载之前如何正确等待所有数据? Is there some different way to achieve this?有什么不同的方法可以实现这一目标吗?
function App() {
const [download, setDownload] = useState([])
const downloadLink = useRef()
const downloadMyCollection = async () => {
const myCollection = collection(db, 'myCollection')
const data = await getDocs(myCollection)
setDownload(data.docs.map((doc) => ({...doc.data(), id: doc.id})))
downloadLink.current.click()
}
return (
<div>
<button
className="downloadButton"
onClick={ downloadMyCollection }>
Download Responses
</button>
<a
href={`data:text/json;charset=utf-8,${encodeURIComponent(
JSON.stringify(download)
)}`}
download='export.json'
className='hidden'
ref={downloadLink}>
isHidden
</a>
</div>
)
}
I don't know 100% if this will work, the fact is that setState
Hook is asyncronous, so even setDownload
will run before the click, the download state will be an empty array when the click()
event run.我不知道 100% 这是否有效,事实是setState
Hook 是异步的,所以即使setDownload
会在点击之前运行,当click()
事件运行时,下载 state 将是一个空数组。
My suggestion is to create an Hooks that listen to download state, and check if isn't empty and then fire the click event.我的建议是创建一个监听下载 state 的 Hooks,检查它是否为空,然后触发点击事件。
function App() {
const [download, setDownload] = useState([])
const downloadLink = useRef()
const downloadMyCollection = async () => {
const myCollection = collection(db, 'myCollection');
const data = await getDocs(myCollection);
setDownload(data.docs.map((doc) => ({...doc.data(), id: doc.id})))
};
useEffect(() => {
if(!!download.length) downloadLink.current.click();
},[download]}
return (
<div>
<button
className="downloadButton"
onClick={ downloadMyCollection }>
Download Responses
</button>
<a
href={`data:text/json;charset=utf-8,${encodeURIComponent(
JSON.stringify(download)
)}`}
download='export.json'
className='hidden'
ref={downloadLink}>
isHidden
</a>
</div>
)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.