【问题标题】:Nested Firebase query React Native not show the result (EXPO)嵌套的 Firebase 查询 React Native 不显示结果(EXPO)
【发布时间】:2020-07-07 10:47:36
【问题描述】:

我有一个 Firebase 数据库,其中包含一个使用 Expo 的 React-Native 项目。我可以毫无问题地从数据库中获取数据。当我尝试对多对多关系进行嵌套 Firebase 查询时,问题就出现了。这是我的一段代码:


    useEffect(() => {
        setUser(firebase.auth().currentUser);
    });

    useEffect(() => {
        if (user) {
            async function getCertificates() {
                await firebase
                    .database()
                    .ref("/user_fav")
                    .child(user.uid)
                    .on("value", (querySnapShot) => {
                        const cert = [];
                        const temp = [];
                        querySnapShot.forEach((item) => {
                            temp.push(item.key);
                            firebase
                                .database()
                                .ref("/certificates")
                                .child(item.key)
                                .on("value", (querySnapShot) => {
                                    cert.push({
                                        name: querySnapShot.val().name,
                                        description: querySnapShot.val()
                                            .description,
                                        years: querySnapShot.val().years,
                                        key: querySnapShot.val().key,
                                    });
                                });
                        });
                        setData(cert);
                        setLoading(false);
                    });
            }

            getCertificates();
        }
    }, []);

首先,我获取 UID 的用户。我进行查询,询问特定用户的证书(成功,临时数组已填充)。然后,我尝试获取证书,但这就是问题所在。

Expo 首次呈现应用程序时,我看不到证书。数组为空。当我保存文档(并重新渲染 Expo)时,证书就会出现。

这很奇怪,我不知道问题出在哪里。

非常感谢。

【问题讨论】:

    标签: javascript firebase react-native firebase-realtime-database expo


    【解决方案1】:

    所有数据都是从 Firebase 异步加载的。

    您的setDate(cert) 现在在您的cert.push(...) 运行之前运行。

    您可以通过放置一些日志语句最轻松地看到这一点:

    console.log("Before attaching first listener");
    firebase
        .database()
        .ref("/user_fav")
        .child(user.uid)
        .on("value", (querySnapShot) => {
            console.log("Got first data");
            querySnapShot.forEach((item) => {
                console.log("Before attaching nested listener");
                firebase
                    .database()
                    .ref("/certificates")
                    .child(item.key)
                    .on("value", (querySnapShot) => {
                        console.log("Got second data");
                    });
            });
            console.log("After attaching nested listeners");
        });
    console.log("After attaching first listener");
    

    当你运行这段代码时,它会打印:

    在附加第一个监听器之前

    附加第一个监听器后

    得到第一个数据

    在附加嵌套监听器之前(可能是这个的多个)

    附加嵌套监听器后

    获得第二个数据(与您添加的嵌套侦听器一样多)

    因此,当您调用 setState 时,cert 尚未填充数据库中的数据。

    解决方案总是一样的:任何需要从数据库中获取数据的代码,都需要在获取该数据的回调中,或者从那里调用。

    所以在你的情况下:

    await firebase
        .database()
        .ref("/user_fav")
        .child(user.uid)
        .on("value", (querySnapShot) => {
            const cert = [];
            const temp = [];
            querySnapShot.forEach((item) => {
                temp.push(item.key);
                firebase
                    .database()
                    .ref("/certificates")
                    .child(item.key)
                    .on("value", (snapshot) => {
                        cert.push({
                            name: snapshot.val().name,
                            description: snapshot.val()
                                .description,
                            years: snapshot.val().years,
                            key: snapshot.val().key,
                        });
                        setData(cert);
                        setLoading(false);
                    });
            });
        });
    

    每次您的嵌套侦听器之一获取任何数据时,上述设置数据。如果您只想在他们都至少收到一次数据后执行此操作,您可以保留一个计数器来跟踪收到数据的回调数量,并将其与querySnapShot.length 进行比较。

    另见:

    【讨论】:

    • 你太棒了!非常感谢您的回复!现在我明白它是如何工作的了!现在,我测量 querySnapShot 的长度(使用 .numChildren();),然后调用 setData(cert) 和 setLoading(false)。它有效!再次感谢您^^
    猜你喜欢
    • 2019-01-26
    • 1970-01-01
    • 2020-02-03
    • 1970-01-01
    • 1970-01-01
    • 2020-05-05
    • 2021-10-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多