【问题标题】:React useEffect to get firestore data once反应 useEffect 以获取一次 Firestore 数据
【发布时间】:2020-07-25 11:35:00
【问题描述】:

我正在尝试弄清楚如何使用 react useEffect 从 firestore 获取数据。

这是我目前的尝试。

import React, { useHook, useEffect, useState } from 'react';
import {
    useParams
  } from 'react-router-dom';

import Firebase from "../../../firebase";

 const ReadBlogPost = async () => {
    const [loading, setLoading] = useState(true);
    const [currentPost, setCurrentPost] = useState([]);
    let { slug } = useParams();


      useEffect(()  =>  {
          Firebase
          .firestore
          .collection("blog")
          .doc(slug)
          .get()
          .then(function(doc) {
            if (doc.exists) {
                // setCurrentPost(doc.data());
                console.log("Document data:", doc.data());
            } else {
                // doc.data() will be undefined in this case
                console.log("No such document!");
            }
          })
          .catch(function(error) {
            console.log("Error getting document:", error);
        }), []
      })

    return (
        <div>

                    {currentPost.title}


        </div>
    )

};
export default ReadBlogPost;

最后的空数组是试图确保 react 不会用尽所有在 this postthis issue 中详述的 Firestore 读取权限。

当我尝试这个时,我收到一条错误消息:

第 19:11 行:预期的是赋值或函数调用,但看到的是 一个表达式 no-unused-expressio

文件是 jsx。我见过this postthis,这意味着我必须将if 语句转换为三元条件。

我将其更改为三元表达式的尝试是:

useEffect(()  =>  {
          Firebase
          .firestore
          .collection("blog")
          .doc(slug)
          .get()
          .then(function(doc) {
            doc.exists? setCurrentPost(doc.data()) :  console.log("No such document!")
          })
          .catch(function(error) {
            console.log("Error getting document:", error);
        }), []
      })

当我尝试这个时,我得到了与我使用 if 语句时相同的错误消息。

谁能提供一个使用 useEffect 读取 jsx 文件中的 Firestore 数据(一次)的示例吗?

下一次尝试 根据 Nicholas 的建议,我将 useEffect 更改为:

useEffect(()  =>  {
          Firebase
          .firestore
          .collection("blog")
          .doc(slug)
          .get()
          .then(function(doc) {
            doc.exists? setCurrentPost(doc.data()) :  console.log("No such document!")
          .catch(function(error) {
                console.log("Error getting document:", error)
          })  
        }, [])
      })

这会产生一个错误提示:

错误:对象作为 React 子级无效(找到:[object 承诺])。如果您打算渲染一组孩子,请使用 代替数组。

下一次尝试

我尝试了 Ben 的建议 - 将 currentPost 中的对象更改回数组,但我得到了与尝试 Nicholas 的建议时相同的错误。

然后,我尝试像这样合并它们:

import React, { useHook, useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';

import Firebase from "../../../firebase";

const ReadBlogPost = async () => {
    let { slug } = useParams();
    const [loading, setLoading] = useState(true);
    const [currentPost, setCurrentPost] = useState([]);



    useEffect(() => {

        const fetchData = async() => {

            try {
                const response = await Firebase.firestore
                    .collection("blog")
                    .doc(slug)
                    .get()
                    .then(function(doc) {
                        doc.exists? setCurrentPost(doc.data()) :  console.log("No such document!")


                    }) 
                } catch(err) {
                    console.error(err);
                }   
            };         


        fetchData();

    }, []);


    return (
        <div>

            {!loading && 
currentPost.title}


        </div>
    )

};
export default ReadBlogPost;

我仍然遇到同样的错误。

错误:对象作为 React 子级无效(找到:[object 承诺])。如果您打算渲染一组孩子,请使用 代替数组。 在 ReadBlogPost(由 Context.Consumer 创建)

我不知道这是否有线索,但 ReadBlogPost 参考表明我在某处有上下文使用者。我还没有创建上下文 - 所以不确定它是否正在寻找能够使用 useEffect 的上下文?

【问题讨论】:

  • 还没试过链接,但也许你需要做.firestore()?
  • 感谢 Eliya - firestore() 在我的配置中被定义为 firestore - 所以它是正确的,但感谢您查看

标签: javascript reactjs google-cloud-firestore jsx


【解决方案1】:

当使用 useEffect 获取数据时,它期望进行同步调用。从 Firestore 请求数据将是异步的,因此为了解决这个问题,我们可以添加一个包装 firestore 调用的函数,称为 fetchData,如下所示:

import React, { useHook, useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import Firebase from "../../../firebase";

function ReadBlogPost () {
    const [loading, setLoading] = useState(true);
    const [currentPost, setCurrentPost] = useState({});
    let { slug } = useParams();


    useEffect(() => {

        const fetchData = async() => {

            try {

                const response = await Firebase.firestore()
                    .collection("blog")
                    .doc(slug)
                    .get();

                console.log('response', response);

                let data = { title: 'not found' };

                if (response.exists) {
                    data = response.data();
                }

                setCurrentPost(data);
                setLoading(false);

            } catch(err) {
                console.error(err);
            }

        };

        fetchData();

    }, []);

    return (
        <div>

            {!loading && currentPost.title}


        </div>
    )

};
export default ReadBlogPost;

我假设你的 currentPost 可能是一个对象而不是一个数组,因为你也在 JSX 中要求标题 - 我已经在 fetchData 中的 Firestore 调用之后添加了 setCurrentPost。希望这会有所帮助

更新:我已将组件的设置更改为命名同步组件(删除了顶部的 const 并删除了异步),我还注意到您提到您将 currentPost 更改回数组 - 请确保它是一个对象,因为您将 JSX 中的 currentPost 作为对象引用 - 我只是使用我在本地使用我自己的 firestore 数据库编写的代码,并成功地从这个 useEffect 中获取了详细信息。请尝试复制上面的整个 sn-p。如果它不起作用,我会要求您也从您导入的 ../firebase 中粘贴您的 Firestore 参考代码。另外请尽量不要将 .then.catch 与 try {} catch {} 块混合,因为它们正在尝试做同样的事情

【讨论】:

  • 谢谢本。当我尝试这个时,我收到一条错误消息:错误:对象作为 React 子项无效(找到:[object Promise])。如果您打算渲染一组子项,请改用数组。
  • 我将 currentPost 改回了一个数组——我只是想在添加所有其他属性之前让标题呈现——但我仍然无法通过此错误消息。非常感谢您提供帮助。
【解决方案2】:

你的依赖数组放错了地方。通过重新格式化以突出问题,您正在这样做:

  useEffect(() => {
    Firebase.firestore
      //...
      .catch(/*...*/), [];
  });

...由于comma operator,这在技术上是合法的javascript。但是由于这可能是一个错误,因此您的 linter 指出了这一点。

相反,您应该这样做:

  useEffect(() => {
    Firebase.firestore
      //...
      .catch(/*...*/);
  }, []);

【讨论】:

  • 当我像下面这样尝试时,我收到了一个新错误。我编辑了帖子以显示发生了什么。
猜你喜欢
  • 2022-08-11
  • 2021-07-27
  • 2020-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-10
  • 2021-06-29
相关资源
最近更新 更多