【问题标题】:React Hooks in combination with Firebase data not showing on page loadReact Hooks 结合 Firebase 数据未在页面加载时显示
【发布时间】:2019-08-14 21:44:37
【问题描述】:

我想将 React Hooks 功能与 Firebase 结合使用。但是现在设置数据时,结果仅在更新 DOM 时可见。 我当前的代码是:

import React, { useState, useEffect } from 'react';
import firebase, { getPivotFunction } from '../../firebase';

/**
* Return a styled component
*/
const ListCards = () => {
  const [data, setData] = useState([]);

  const userListsRef = firebase
    .database()
    .ref('userLists')
    .child('1234d343f');

  useEffect(() => {
    (async function() {
       try {
         const response = await getPivotFunction(userListsRef, 'lists');
         setData(response);
       } catch (e) {
         console.error(e);
       }
    })();
  }, []);

 /**
 * Return all list cards
 */
 return (
  <ul>
    {data.map(item => (
      <li key={item.time}>dummy text</li>
    ))}
  </ul>
 );
};

第一次渲染页面时,不会显示“虚拟文本”,只有在触发更新时才会显示。 我的目标是在页面加载完成并且data 的长度不为 0 时让“虚拟文本”出现。

在这种情况下,getPivotFunction 包含:

/** Get FireBase data based on a pivot table */
const getPivotFunction = (ref, target) => {
  let dataArray = [];

  ref.once('value', userInfo => {
    userInfo.forEach(function(result) {
      firebase
        .database()
        .ref(target)
        .child(result.key)
        .on('value', snapshot => {
          dataArray.push(snapshot.val());
        });
    });
  });

  return dataArray;
};

请告诉我

【问题讨论】:

  • 你能显示你的文本组件吗
  • 我更新了代码,所以不需要 Text 组件,但问题仍然存在
  • 你为什么要在 useEffect 中那样使用异步函数?
  • @RonaldZwiers 行为似乎是正确的,只有当数据可用时,数据的长度才会大于零并显示虚拟文本,在此之前数组为空

标签: reactjs firebase firebase-realtime-database react-hooks


【解决方案1】:

您的 getPivotFunction 是一个依赖回调的异步函数,而使用 async await on 这不是正确的方法。相反,您需要有一个回调

/** Get FireBase data based on a pivot table */
const getPivotFunction = (ref, target, callback) => {
  const dataArray= [];
  ref.once('value', userChats => {
    var i = 0;
    userChats.forEach(function(result) {
      firebase
        .database()
        .ref(target)
        .child(result.key)
        .on('value', snapshot => {
          i++;
          dataArray.push(snapshot.val());
          if(i === userChats.length) {
             callback(dataArray)
          }
        });
    });
  });
};

并像使用它

/**
* Return a styled component
*/
const ListCards = () => {
  const [data, setData] = useState([]);

  const userListsRef = firebase
    .database()
    .ref('userLists')
    .child('1234d343f');

  useEffect(() => {
      getPivotFunction(userListsRef, 'lists', (response) => {
         setData(response);
      });
  }, []);

 /**
 * Return all list cards
 */
 return (
  <ul>
    {data.map(item => (
      <li key={item.time}>dummy text</li>
    ))}
  </ul>
 );
};

【讨论】:

    【解决方案2】:

    Hooks 不适用于这样的异步函数。这样的事情应该可以工作:

    const ListCards = () => {
      const [data, setData] = useState([]);
      const [loaded, setLoaded] = useState(false);
    
      ... 
    
      useEffect(() => {
        getPivotFunction(userListsRef, 'lists')
        .then(data => { setData(data); setLoaded(true)});
      }, []);
    };
    

    然后仅在 loadedtrue 时渲染。

    【讨论】:

    • 这不正确。 OP 使用了一种在 useEffect 中编写异步函数的方法。你可以检查这个stackoverflow.com/questions/53332321/…
    • 是的,您可以这样做,但不推荐这样做。您链接的问题甚至说这是一种“解决方法”。
    • 它是一个匿名函数,在效果运行时调用,它允许你使用await
    猜你喜欢
    • 1970-01-01
    • 2021-01-16
    • 1970-01-01
    • 2022-01-25
    • 2018-12-04
    • 2022-08-04
    • 2020-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多