• Empleos
  • Sobre nosotros
  • profesionales
    • Inicio
    • Empleos
    • Cursos y retos
    • Preguntas
    • Profesores
  • empresas
    • Inicio
    • Publicar vacante
    • Nuestro proceso
    • Precios
    • Pruebas Online
    • Nómina
    • Blog
    • Comercial
    • Calculadora de salario

0

330
Vistas
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>
    )
}
almost 3 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

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>
    )
}
almost 3 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Nuestro proceso Comercial
Legal
Términos y condiciones Política de privacidad
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recomiéndame algunas ofertas
Necesito ayuda