Попытка экспортировать данные в csv-файл из моих данных firebase дает undefined

# #javascript #reactjs #firebase #csv #react-hooks

Вопрос:

У меня есть список данных из моего firebase firestore, которые я хочу экспортировать в .csv

Я сделал все, что требуется, но когда я добавляю значения, которые я хочу экспортировать, они всегда не определены.

Я не эксперт в react, я несколько промежуточный, но я думаю, это потому, что я устанавливаю свои данные внутри 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>
    )
 

Комментарии:

1. Выборка данных из firebase является асинхронной, поэтому данные будут неопределенными при реализации прямо сейчас.

Ответ №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>;

 

Комментарии:

1. я получаю data.map теперь не является функцией, когда я использую этот код.

2. мне нужно, чтобы состояние использования моих данных не зависело от отчета csv.

Ответ №2:

Вы должны все состояния координации / обновления useState и useEffect перехватывать и не полагаться на какие-либо обновления полей, выходящие за рамки этих.

Затем вы должны удалить 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>
)
 

Возможно, вам потребуется добавить состояние загрузки, чтобы отразить влияние загружаемых данных на пользовательский интерфейс.

Комментарии:

1. я получаю сообщение об ошибке при попытке чтения этого кода: » Данные должны быть «Строкой», «массивом массивов» ИЛИ «массивом объектов», я полагаю, это из-за data:userData в csvReport

2. мне нужно, чтобы мои setData отличались от отчета csv, здесь вы нажимаете csvReport, что приведет к тому, что пользователи не будут выбраны для меня, когда я попытаюсь получить своих пользователей в свою таблицу

Ответ №3:

Я думаю, что есть две вещи, которые вызывают проблему и которые вам нужно понять.

  1. Асинхронная функция
  2. Жизненный цикл реакции

Извлечение данных из firebase является асинхронным и может занять некоторое время, прежде чем вы получите возвращаемые данные, пока вы сохранили csvReport их как постоянные переменные и настроили как свойства элемента React. Таким образом, когда firebase все еще загружает ваши данные, а ваш компонент react уже отрисован / смонтирован, ваше data состояние имеет значение [] от значения по умолчанию, как определено в useState инструкции. Основываясь на вашем коде, ваша csvReport постоянная переменная не будет получать новые данные из firebase, если ваше приложение не будет повторно отрисовано (введите новый жизненный цикл и повторите). Например, переключиться на другой компонент вкладки и вернуться к этому компоненту без обновления браузера.

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

Таким образом, простое решение СОСТОИТ в том, чтобы НЕ сохранять данные как постоянную переменную, а настраивать свойства элемента React непосредственно из вашей переменной useState. Основываясь на вашем коде, я бы внес некоторые изменения, подобные этому.

 ...your previous code

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

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

 

Надеюсь, это поможет и получайте удовольствие от внесения изменений 🙂

Комментарии:

1. по-прежнему не работает, потому что данные не определены в CSVLink