【问题标题】:set state in useEffect based on the result of a Promise根据 Promise 的结果在 useEffect 中设置状态
【发布时间】:2021-03-13 05:18:54
【问题描述】:

我正在使用 ReactNative 和 FireStore 进行项目。

我必须渲染从服务器检索到的数据。

我不关心数据的短期更新,我只需要检索一次数据。

这是一般情况。

更具体地说,我想将获取的数据存储在一个状态中。渲染基于此状态。获取后的状态应该是这样的:

list = [{category:"ct1",items:[obj1,obj2,obj3,...]},{category:"ct2",items:[obj1,obj3]}]

如果我使用下面的代码没有渲染,详细来说我有 2 个问题。

  1. console.log(list) 显示列表(状态)为空,但 console.log(results) 有效。
  2. 一段时间后,控制台显示此错误:Rendered more hooks than during the previous render.
const [list, setList] = useState([]);

function getData() {
    const final = []
    const categories = ["ct1", "ct2", "ct3", "ct4"]
    var promises = categories.map((category) => {
        return db.collection('items')
            .where("category", "array-   contains", category)
            .get()
            .then((querySnapshot) => {
                const items = [];
                querySnapshot.forEach((doc) => {
                    items.push(doc.data())
                });
                final.push({
                    category: category,
                    items: items
                })
            })
    })
    Promise.all(promises).then(function(results) {
        console.log("final", final)
        //this print [{category:"ct1",items:[obj1,obj2,obj3,...]},{categor
        setList(final)
        //so I have the final array, I can set the state
        console.log("list", list)
        //when I call this list is empty

    })
};

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

return ({
    list.map((item, index) => (
        ......
        //this function iterate over the list, is very long and works.
        //I have tested on a predefined state. So the problem is not this.
    ))
})

【问题讨论】:

  • 格式化代码,合理的缩进会让别人更容易帮助你理解问题。
  • 您的代码看起来不错。我不认为“Rendered more hooks than during the previous render.”错误来自您发布的部分。
  • 看看这个对managing an asynchronous call 的出色回答可能是个好主意? async and await 的 Promises 在这里很有趣。它可以解释为什么你的状态是空的。也许重组你的代码会是一个更好的选择。

标签: javascript react-native google-cloud-firestore promise


【解决方案1】:

当 Promise.all 被解析时尝试填充最终的数组:

function getData() {
    const final = [];
    const categories = ["ct1", "ct2", "ct3", "ct4"];
    var promises = categories.map((category) => {
      return db
        .collection("items")
        .where("category", "array-   contains", category)
        .get();
    });
    Promise.all(promises).then(function (results) {
      results.map((querySnapshot) => {
        const items = [];
        querySnapshot.forEach((doc) => {
          items.push(doc.data());
        });
        final.push({ category: category, items: items });
      });
      console.log("final", final); //this print [{category:"ct1",items:[obj1,obj2,obj3,...]},{categor
      setList(final); //so I have the final array, I can set the state
    });
  }

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

【讨论】:

    猜你喜欢
    • 2021-03-26
    • 2020-08-26
    • 2021-08-30
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 2017-07-18
    • 2021-10-17
    • 1970-01-01
    相关资源
    最近更新 更多