简体   繁体   中英

Undefined is not an object React Native and Firebase

I'm building a React-Native app using CRNA (Node: v9.3.0, npm: 4.6.1, RN: 0.50.4 React: 16.0.0).

My console give mi the following error: "undefined is not an object (evaluating 'secciones.forEach')"

The code that have the bug is the following:

async buscarProfesores(secciones) {
    const profesores = [];
    secciones.forEach(seccion => {
        firebase.database().ref(`/Usuarios/${seccion.profesor}`).on('value', async snapshot => {
            const prof = snapshot.val();
            await profesores.push(prof.nombre);
        }); 
    });
    return await profesores;}


async buscarSecciones() {
    try {
        const usuario = firebase.auth().currentUser.uid;
        let secciones;
        await firebase.database().ref(`/Usuarios/${usuario}`)
            .on('value', snapshot => {
                secciones = snapshot.val().secciones;
                return false;
            });
        return secciones;
    } catch (error) {
        console.log(error);
    }
}

I'm calling the buscarProfesores function is this snippet:

async auxiliar() {
    try {
        const secciones = await this.buscarSecciones();
        const profesores = await this.buscarProfesores(secciones);
        const data = await this.armarSnapshot(secciones, profesores);
        return data;
    } catch (error) {
        console.log(error);
    }
}

I think I can identify some of the problems in the code,

buscarProfesores :

async buscarProfesores(secciones) {
    let profesores = []; // Not 'const', because 'profesores' is not read-only
    secciones.forEach((seccion) => {
        firebase.database().ref(`/Usuarios/${seccion.profesor}`).once('value', (snapshot) => {
            profesores.push(snapshot.val().nombre);
            // It shouldn't be 'async (snapshot) => { ... }', because
            // What you're doing here is not an async operation, you're simply
            // pushing something into an array. If anything is async, it's this:
            //
            // secciones.forEach(async (seccion) => { firebase.database()... });
        });
    });

    // await return profesores
    // Again, there shouldn't be 'await' here, and even if there isn't await here,
    // all you'll get is an empty array, because 'firebase.database()...' is an
    // async operation, it will be executed, but it will take some amount of time,
    // and meanwhile, the rest of the function will be executed at the same time,
    // meaning that, the return statement will be executed immediately, therefore,
    // you have an empty array
}

Therefore, you should re-write your buscarProfesores function. You got it almost perfect in buscarSecciones() function, just write this function in the same fashion and you're on the right track. However, what's different is that you are fetching many things from the database and putting them in an array in this function, you need a little help of Promise.all() here:

async buscarProfesores(secciones) {
    let promises = [];
    secciones.forEach((seccion) => {
        promises.push(firebase.database().ref(`/Usuarios/${seccion.profesor}`).once('value'));
    });

    await Promise.all(promises)
        .then((results) => {
            let profesores = [];
            results.forEach((result) => {
                profesores.push(result.val().nombre);
            });

            return profesores;
        })
        .catch((error) => {
            console.log(error);
            return [];
        });
}

Promise.all() takes an array of promises and execute them, only when all of the promises are successfully executed will the .then() be executed later, otherwise the .catch() will be executed

There's not much problem with buscarSecciones() function, simply change .on to .once , and delete return false statement

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM