首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用useEffect()挂钩和异步/等待从Firebase/Firestore获取数据

使用useEffect()挂钩和异步/等待从Firebase/Firestore获取数据
EN

Stack Overflow用户
提问于 2019-10-04 05:59:48
回答 3查看 2K关注 0票数 12

1.我的意图:

使用

useEffect()

钩子从props中初始化组件的状态变量,它的数据是使用以下命令从firebase中提取的

mapStateToProps()

..。

2.问题:无法初始化组件的状态变量

这个想法是,当组件挂载时,useEffect将只运行一次。在这个初始化窗口中,我希望将数据从firebase加载到该组件的本地状态变量。

它在以下情况下工作得很好

运行本教程中的示例

..。在其中,他使用axios()在

异步/等待

函数。有关他的代码,请参阅下面的第3节。

但当我这样做时,试图从props获取数据,而props是与Firestore同步或由Firestore初始化的,我总是得到null,无法从

从我的async/await函数返回。

我想这是因为我对async/await缺乏理解。我无法创建有效的

异步/等待

函数从props中检索数据。

问题:

我怀疑这就是问题所在。那么,什么才是编写

异步/等待

哪个函数可以正确地从与firebase同步的道具中检索数据?

我的问题代码:

代码语言:javascript
运行
复制
import React, { useState, useEffect} from "react";
    import { connect } from "react-redux";
    import { firestoreConnect } from "react-redux-firebase";
    import { compose } from "redux";

    const app = props => {
      const { order } = props;  
      const [data, setData] = useState({});

      useEffect(() => {
        const fetchData = async () => {
          const result = await (() => {
            return new Promise(resolve => {
              if (order) { resolve(order); }
            });
          })();
          setData(result);
        };
        fetchData();
      }, []);
      /** if I leave useEffect's second argument empty, which is intended to run only once at the beginning, then i'm getting null  */

    ...

    const mapStateToProps = state => {
      const id = "DKA77MC2w3g0ACEy630g"; // docId for testing purpose.
      const orders = state.firestore.data.orders;
      const order = orders ? orders[id] : null;        
      return {
        order: order
      };
    };

    export default compose(
      connect(mapStateToProps),
      firestoreConnect([{collection: "orders"}])
    )(app);

我尝试过的:

如果我添加

订单

添加到第二个参数中,那么它将正确地将数据加载到组件的状态变量中。但它会将道具的数据重新加载到组件的状态变量中,并在每个重新渲染周期中擦除任何更改。

代码语言:javascript
运行
复制
useEffect(() => {
        ...
      }, [order]);

mapStateToProps()

在初始组件挂载后发生?因为这将解释为什么在最初的效果中,道具总是空的。

3.我遵循的教程:使用钩子获取数据

我能够使用以下命令成功获取数据

本教程中的技术

代码语言:javascript
运行
复制
const [data, setData] = useState({ hits: [] });
  useEffect(() => {
    const fetchData = async () => {
      const result = await axios(
        "https://hn.algolia.com/api/v1/search?query=redux"
      );
      setData(result.data);
    };
    fetchData();
  }, []);
EN

回答 3

Stack Overflow用户

发布于 2021-02-10 09:21:49

听起来像是

可以是父级每次创建的对象。钩子依赖关系检查是否完全匹配--

--因此,即使对象内部的值不变,如果对象本身发生变化,效果也会再次运行。

最常见的方式是传递普通的对象文字:

代码语言:javascript
运行
复制
const order = { id: 'foo', SKU: 'bar', cost: 19.95, quantity: 1 };
return ;

这将重新填充

每次都使用新的对象字面量。当您将一个对象扩展到另一个对象中时,会出现更隐蔽的重新创建文字的情况:

代码语言:javascript
运行
复制
const order = { ...oldOrder, quantity: 2 };

这仍然会创建一个新对象。

不要试图改变现有的对象。

React会开始对你做非常奇怪的事情。一旦你理解了钩子依赖是如何工作的,变异的对象就会让你陷入困境。

您有三种选择:

使用原语作为依赖项

如果你能找出

应该

从服务器强制刷新,将其放入其自己的变量中,并根据该变量设置依赖项。只有当您只需要向服务器发送有限数量的字段时,这才能很好地工作。

如果,在您的示例中,您只需要订单的

要进行调用,您可以将其提取到它自己的变量中:

代码语言:javascript
运行
复制
const orderId = order.id;

useEffect(() => {
  const fetchData = async () => {
    const response = await axios(`url-with-id?orderId=${orderId}`);
    setData(response.data);
  };
  fetchData();
}, [orderID]);

请注意,如果您尝试访问整个

对象,即使你没有将它包含在依赖数组中,React也会报错,这是有充分理由的。除非你能绝对保证它永远不会改变,除非

也会改变,它可能会导致运行时错误,这些错误将在以后攻击您。只能在效果中使用依赖数组中的内容。

记忆你的对象

如果你的

对象非常简单,你可以根据它的内容来记忆它。

以同样的方式获取依赖项数组

这样做,但不是在依赖项发生变化时运行效果,

每当依赖项发生更改时,都会返回一个新对象。

只要没有任何依赖关系改变,

返回相同的对象。

这就是为什么它有效的关键。

如果

有几个简单的值,例如

,以及

,您可以将您的对象文字创建更改为如下所示:

代码语言:javascript
运行
复制
const order = useMemo(
  () => ({
    id,
    SKU,
    price,
    quantity
  }),
  [id, SKU, price, quantity]
);

现在,只要没有任何数字或字符串

更改,则每次渲染都将获得相同的对象。因为它是同一个物体,

将只运行一次。如果其中一个值发生更改,则新的

对象将被提供,

的依赖关系数组被更改,并为新的

..。

查看一下为什么你会不断更新

对象

在你的情况下,看起来你得到了你的

来自Redux存储的对象。Redux依赖于它的数据只有在必要的时候才会改变。每次Redux中的数据发生更改时,都会触发每个需要它的组件中的更改。如果数据发生了不必要的更改,这可能会导致您获取不断更新的对象。

您需要查看是否有另一个组件将不必要的操作分派到Redux,或者您的reducer是否在不需要时意外地创建了所有新对象。家长是否在没有检查是否需要的情况下进行更新?您是否有异步操作(thunks或sagas)对您的数据存储进行大量更新?在简单地在旧数据之上写入新数据之前,您是否检查了传入数据和现有数据之间的增量?

Redux状态管理本身就是一个完整的主题。它可能更容易使用

Redux工具包

也不愿自己动手。它负责需要在存储中重新创建的内容,而不必管理不变性问题。如果FireBase数据故意覆盖你的数据,Redux Toolkit可能会让你更容易确保只更新在调用之间更改的数据,而不是一直在更改所有数据。

票数 1
EN

Stack Overflow用户

发布于 2020-12-26 02:28:18

试试这个:

代码语言:javascript
运行
复制
const app = props => {
        const [data, setData] = useState({ results: [] });
          useEffect(() => {
            const getData = async () => {
              const result = await axios('Your URL here');
              setData(result.data);
            };
            getData();
          }, []);

    ...
票数 0
EN

Stack Overflow用户

发布于 2021-03-01 17:05:50

试试这个:

代码语言:javascript
运行
复制
const app = props => {
        const [data, setData] = useState({ results: [] });

          const getData = async () => {
              const result = await axios('Your URL here');
              setData(result.data);
            };

          useEffect(() => {
            getData();
          }, []);

          ...
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58227421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档