# #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:
Я думаю, что есть две вещи, которые вызывают проблему и которые вам нужно понять.
Извлечение данных из 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