【问题标题】:Trying to export data to csv file from my firebase data gives undefined尝试将数据从我的 firebase 数据导出到 csv 文件给出未定义
【发布时间】:2021-12-21 11:35:37
【问题描述】:

我有一个我想导出到 .csv 的 firebase firestore 中的数据列表

我做了所有需要的事情,但是当我添加要导出的值时,它们总是未定义。

我不是反应专家,我有点中级,但我认为这是因为我将数据设置在 useEffect Hook.

我的数据 useState 未定义,尽管它包含值并且我可以在我的表中看到它们,这导致 CSVLink 抛出错误。

我如何允许将我的数据传递到标头中?

这是我的代码:

  const [data, setData] = useState([]);
  const [id, setID] = useState("");
  const list = []
  const filteredList = []
  useEffect(() => {
    firebase.firestore().collection("Users").get().then((userSnapshot) => {

      userSnapshot.forEach((doc) => {
       
        const {powerAccount,first_name,registerDate,email,company,country,phone} = doc.data();
        setID(doc.data().usersID)
        list.push({
          usersID:doc.id,
          powerAccount:powerAccount,
          first_name:first_name,
          registerDate:registerDate,
          email:email,
          company:company,
          country:country,
          phone:phone,
        });
      });
      setData(list);
    });
  },[]);


const headers = [
                  // here all the keys give undefined.
    {label:'User',key:data.usersID},
    {label:'Account',key:data.powerAccount},
    {label:'Name',key:data.first_name},
    {label:'RegistrationDate',key:data.registerDate},
    {label:'Email',key:data.email},
    {label:'Company',key:data.company},
    {label:'Country',key:data.country},
    {label:'Phone',key:data.phone},
  ];

 const csvReport = {
    filename:"userReport.csv",
    headers:headers,
    data: data // also my data useState is undefined, although it holds values and i can see them in my table
  }

    return (
     <CSVLink  {...csvReport} >
            Export
     </CSVLink>
    )

【问题讨论】:

  • 从 firebase 获取数据是异步的,因此在您现在实施时数据将是未定义的。

标签: javascript reactjs firebase csv react-hooks


【解决方案1】:

根据您的实现,从 firebase 获取数据是异步的,因此 csvData 变得未定义,因为它在状态更新后没有更新 尝试像这样更改您的代码,让我知道它是否可以正常工作

const [data, setData] = useState({
  filename: "userReport.csv",
  headers: [],
  data: [],
});
const [id, setID] = useState("");
const filteredList = [];
useEffect(() => {
  firebase
    .firestore()
    .collection("Users")
    .get()
    .then((userSnapshot) => {
      let list = [];
      userSnapshot.forEach((doc) => {
        const {
          powerAccount,
          first_name,
          registerDate,
          email,
          company,
          country,
          phone,
        } = doc.data();
        setID(doc.data().usersID);
        list.push({
          usersID: doc.id,
          powerAccount: powerAccount,
          first_name: first_name,
          registerDate: registerDate,
          email: email,
          company: company,
          country: country,
          phone: phone,
        });
      });
      const headers = [
        // I'm not sure why you need this key
        // but if it's only for uniqueness
        // you can replace them by unique strings like
        // { label: "User", key: "user" },
        // { label: "Account", key: "account" },

        { label: "User", key: data.usersID },
        { label: "Account", key: data.powerAccount },
        { label: "Name", key: data.first_name },
        { label: "RegistrationDate", key: data.registerDate },
        { label: "Email", key: data.email },
        { label: "Company", key: data.company },
        { label: "Country", key: data.country },
        { label: "Phone", key: data.phone },
      ];

      const csvReport = {
        filename: "userReport.csv",
        headers: headers,
        data: list,
      };
      setData(csvReport);
    });
}, []);

return <CSVLink {...data}>Export</CSVLink>;

【讨论】:

  • 当我使用此代码时,我正在获取 data.map 不是一个函数。
  • 我需要我的数据使用状态独立于 csv 报告。
【解决方案2】:

您应该将所有状态协调/更新到 useStateuseEffect 挂钩,并避免依赖这些范围之外的任何字段更新。

然后您应该删除list 变量,将状态更新移动到您的效果挂钩并将所有用户数据合并到同一结构中:

const [data, setData] = useState([]);
useEffect(() => {
  firebase.firestore()
    .collection("Users")
    .get()
    .then((userSnapshot) => {
      const usersData = [];
      userSnapshot.forEach((doc) => {
        const { powerAccount, first_name, registerDate, email, company, country, phone, userID } = doc.data();
        const userData = {
          usersID: doc.id,
          powerAccount: powerAccount,
          first_name: first_name,
          registerDate: registerDate,
          email: email,
          company: company,
          country: country,
          phone: phone,
        };
        const headers = [
          // here all the keys give undefined.
          { label: 'User', key: userID },
          { label: 'Account', key: powerAccount },
          { label: 'Name', key: first_name },
          { label: 'RegistrationDate', key: registerDate },
          { label: 'Email', key: email },
          { label: 'Company', key: company },
          { label: 'Country', key: country },
          { label: 'Phone', key: phone },
        ];
        const csvReport = {
          filename: "userReport.csv",
          headers: headers,
          data: userData
        }
        usersData.push(csvReport);
      });
      setData(usersData);
    });
}, []);

return (
  <CSVLink  {...data} >
    Export
  </CSVLink>
)

您可能需要添加加载状态以反映正在加载的数据的 UI 效果。

【讨论】:

  • 我在尝试读取此代码时遇到错误“数据应该是“字符串”、“数组数组”或“对象数组”我相信这是因为数据:userData 在csv报告
  • 我需要我的 setData 与 csv 报告不同,在这里您正在推送 csvReport,这将导致当我尝试将我的用户提取到我的表中时没有为我提取任何用户
【解决方案3】:

我认为有两件事会导致您需要了解问题。

  1. Asynchronous Function
  2. React Lifecycle

从 firebase 获取数据是异步的,当您将 csvReport 保存为常量变量并将其设置为 React 元素属性时,可能需要一段时间才能获得返回的数据。因此,当 firebase 仍在加载您的数据并且您的 react 组件已被渲染/安装时,您的 data 状态的值是 [],而不是 useState 语句中定义的默认值。根据您的代码,您的 csvReport 常量变量将不会从 firebase 接收新数据,除非您的应用程序被重新渲染(进入新的生命周期并重复)。比如切换到其他tab组件,不刷新浏览器就回到这个组件。

const csvReport = {
    filename:"userReport.csv",
    headers:headers, => [{ label: "User", key: undefined }, ...etc]; undefined bcs `data` is []
    data: data => the value is []
  }

所以简单的解决方案是将数据保存为常量变量并直接从您的 useState 变量设置 React 元素属性。根据你的代码,我会做一些这样的改变。

...your previous code

const getHeaders = () => {
  // Do your data manipulation using `data` in useState
  // For example:
  const headers = data && data.map(item => {return {id: item.id}})
  return headers
}

return (
  <CSVLink
    filename="userReport.csv"
    headers={getHeaders()}
    data={data}
  >
     Export
  </CSVLink>
)

希望这对您有所帮助,并在做出改变时玩得开心 :)

【讨论】:

  • 仍然无法正常工作,因为 CSVLink 中未定义数据
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-14
  • 2014-11-05
  • 1970-01-01
相关资源
最近更新 更多