【问题标题】:Setting state before render with ref to firestore在使用 ref 渲染之前设置状态到 firestore
【发布时间】:2021-03-03 04:30:46
【问题描述】:

我正在解决一个简单的逻辑问题,但我似乎无法让事情顺利进行。先分享一下我最有说服力的代码实验,然后再分享一些想法。

useEffect(() => {
    firebase
        .firestore()
        .collection("someCollection")
        .orderBy("date", "desc")
        .onSnapshot(docs => {
            let documents = []
            if (canGetUpdatesFromFirestore.current) {
                docs.forEach((doc) => {
                    documents.push(doc.data())
                })

                if(documents.length > 3) {
                    documents.splice(4, 0, {questionPostId: 0})
                    documents.splice(5, 0, {questionPostId: 1})
                }
                setAllQuestions(documents)
                setUsers(documents)

            }

        })
    if (searchValue.length > 2) {
        canGetUpdatesFromFirestore.current = false;
        functions.searchForSearchVal(searchValue, "Sexuality")
            .then((result) => {
                setAllQuestions(result);
            })
    } else {
        canGetUpdatesFromFirestore.current = true
    }
}, [searchValue])

function setUsers(docs){
    let arrFinal = []
    let copyOfAllQuestions = ""
        for(let i = 0; i< docs.length; i++) {
            console.log("HERE")
            if (docs[i].postedBy) {
                docs[i].ref.get().then(userFire => {
                    copyOfAllQuestions = {
                        ...allQuestions,
                        ...{hasPremium: userFire.data().hasPremium}
                    }
                })
                arrFinal.push(copyOfAllQuestions)
            }

        }
    setAllQuestions(arrFinal)
}

让我分享一下我目前的状态以及我正在努力实现的目标。 我有一个显示 allQuestions。每个问题数据都有一个 ref 指向其在 Firestore 中的用户文档。对于每个问题,我都需要检查该用户是否 hasPremium。我应该如何以正确的方式做到这一点? 目前的问题是我可以通过 ref 从我的 Users 集合中获取数据,但我必须刷新我的状态才能显示所有数据。 有人可以帮我走上正确的道路/请正确思考这个问题吗?

【问题讨论】:

    标签: reactjs firebase react-native google-cloud-firestore


    【解决方案1】:

    我提出的一种方法是采用数据非规范化。也就是说,与其将对其他文档(用户)的引用放在 Questions 文档中,不如将所有相关用户信息直接放入 Questions 文档中。

    这与 SQL 数据库方法是对立的,但没关系,因为 Firestore 是“NoSQL”。拥抱反 SQL 身份!!

    基本上,在您的问题文档中,您希望在处理问题时复制应用中所需的任何信息,并避免通过获取其他文档进行“连接”。您无需将所有用户文档复制到问题文档中 - 只需将您的应用处理问题时所需的元素。

    例如,也许在问题中你需要的只是:

    question: {
        name: ...,
        type: ...,
        lastUpdated: ...,
        postedBy: {
          email: ...,
          displayName: ...,
          avatarUrl: ...,
          hasPremium: true,
        }
    }
    

    对于重复数据,您通常需要一种机制来使重复数据从其“源”保持最新。因此,您可能会考虑为用户文档的onUpdate() 使用 Cloud Function 触发器,并且当修改相关值(emaildisplayNameavatarUrl 和/或hasPremium)时,您将遍历所有问题由该用户发布并相应更新。

    这里的经验法则是:

    • 应用中的一个屏幕/功能所需的所有数据都进入一个文档
    • NoSQL 文档存储用于频繁读取和不频繁写入的地方
    • NoSQL 数据存储(通常)没有“连接” - 所以不要将您的应用设计为需要它们(这就是您上面的代码所做的:加入问题和用户)
    • 通常您并不关心更新所有重复数据的实例(例如,如果用户今天更新了他们的 displayName,您是否应该更新他们 3 年前发布的问题?-- 不同的应用程序/业务需求会给出不同的答案)

    【讨论】:

    • 好主意!感谢您的建议!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 2017-11-11
    • 2020-03-10
    • 2018-09-28
    • 2016-02-05
    • 1970-01-01
    相关资源
    最近更新 更多