简体   繁体   English

使用异步获取 API 数据不渲染

[英]Using async to get API data does not render

I'm pulling data from Firebase in getSubscriptions() which returns an array:我在getSubscriptions()中从 Firebase 中提取数据,它返回一个数组:

[
    {
        "price": 2000.01,
        "product_name": "Awesome product"
    },
    {
        "active": true,
        "product_name": "Other product",
        "Price": 599.99
    }
]

I'm iterating through the array and I'm able to get a result but I'm having trouble getting that result to render.我正在遍历数组,我能够得到一个结果,但我无法得到这个结果来呈现。

I know the issue has something to do with async and waiting for the result to return but I'm stuck on how to apply those concepts to my issue here.我知道这个问题与异步有关并等待结果返回,但我一直坚持如何将这些概念应用于我的问题。

When I uncomment the line useEffect(() => setActiveNotifications(active), [active]) , introducing the useState, the calls are put in an infinite loop calling the Firebase API ad infinitum.当我取消注释行useEffect(() => setActiveNotifications(active), [active]) ,引入 useState 时,调用被置于无限循环中,调用 Firebase API 无限循环。

export default function UserAccount(props) {

  const [activeNotifications, setActiveNotifications] = useState()

  function buildSubscriptions(userId) {
    getSubscriptions(userId).then(active => {
      console.log(JSON.stringify(active, null, 4))  // This returns output above 
      
      // useEffect(() => setActiveNotifications(active), [active])  // This will cause infinite loop 

      return (
        active.map(product =>
          <p key={product.product_name}>{product.product_name}</p>)  // key defined some value to not throw warning 
      )
    })
  }

  async function getSubscriptions(userId) {
    const subPtrCollection = await getUserSubs(userId)
    let a = []
    await Promise.all(subPtrCollection.map(async docId => {  // Promise.all used to execute commands in series
      const docData = await getDocData(docId.product)
      a.push(docData)
    }))
    return a

  }

  return (
    ...
    <Box>{buildSubscriptions(user.uid)}</Box>  // Not important where `user.uid` comes from 
    ...
  )
}

Infinite loop is because the method invoked in render method setting the state and that causes render.无限循环是因为在渲染方法中调用的方法设置了 state 并导致渲染。 Try some thing like below 1) On change of uid, request for build 2) in when you receive the results from api save to state, this cause render 3) in render method used the state data.尝试以下操作 1) 在更改 uid 时,请求构建 2) 当您从 api 收到保存到 state 的结果时,这会导致渲染 3) 在渲染方法中使用 Z9ED39E2EA931586B6A985A6 数据。

export default function UserAccount(props) {
  const [activeNotifications, setActiveNotifications] = useState();

  // when ever uid changes, do the build subscriptions
  useEffect(() => buildSubscriptions(user.uid), [user.uid]);

  // get subscriptions and save to state
  function buildSubscriptions(userId) {
    getSubscriptions(userId).then((active) => setActiveNotifications(active));
  }

  async function getSubscriptions(userId) {
    const subPtrCollection = await getUserSubs(userId);
    let a = [];
    await Promise.all(
      subPtrCollection.map(async (docId) => {
        // Promise.all used to execute commands in series
        const docData = await getDocData(docId.product);
        a.push(docData);
      })
    );
    return a;
  }

  return (
    <Box>
      {activeNotifications.map((product) => (
        <p key={product.product_name}>{product.product_name}</p>
      ))}
    </Box>
  );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM