Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

470
Views
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.

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. 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. I have tried different async and Promise structures to wait for all the data before starting the download but so far I have failed. 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.

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>
    )
}
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

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.

My suggestion is to create an Hooks that listen to download state, and check if isn't empty and then fire the click event.

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>
    )
}
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!