我的 flatList 在我的 api 查询完成之前呈现
Posted
技术标签:
【中文标题】我的 flatList 在我的 api 查询完成之前呈现【英文标题】:My flatList is rendering before my api query finishes 【发布时间】:2022-01-06 21:13:23 【问题描述】:我有一个名为 getRecados() 的异步函数,它可以访问 firebase 并获取我需要我的平面列表来呈现的所有数据:
const getRecados = () =>
setRefreshing(true)
try
const recadosRef = firebase.firestore().collection('recados');
recadosRef.orderBy('timestamp', 'desc').get().then(snapshot =>
const recadosList = new Array()
// Does some filtering on the data it just grabbed from firebase
if (user_setor.length == 0)
snapshot.forEach(doc =>
if ((doc.data().curso_dest == user_curso
|| doc.data().curso_dest == '')
&& (doc.data().ano_dest == user_ano
|| doc.data().ano_dest == '')
&& (doc.data().turno_dest == user_turno
|| doc.data().turno_dest == ''))
recadosList.push(doc)
)
else
snapshot.forEach(doc =>
if (user_setor.includes(doc.data().remetente))
recadosList.push(doc)
)
// fullData is an useState
setFullData(recadosList.map((doc) => (
id: doc.id,
titulo: doc.data().titulo,
timestamp: doc.data().timestamp,
remetente: doc.data().remetente,
curso_dest: doc.data().curso_dest,
ano_dest: doc.data().ano_dest,
turno_dest: doc.data().turno_dest,
texto: doc.data().texto
)))
setLoading(false)
setRecados(fullData)
)
catch (err)
Alert.alert("Erro ao consultar os recados!!!", err.message);
setRefreshing(false)
;
我会在 homeScreen 渲染后立即调用它:
useEffect(() =>
getRecados()
, []);
但是当我第一次打开 homeScreen 时,flatList 是空的,但是当我使用按钮再次执行 getRecados() 时,flatList 工作正常并显示来自 firebase 的数据,所以这让我得出结论 flatList 正在渲染在 getRecados() 可以第一次设置 fullData 的值之前,如何让它等待 getRecados 完成它所做的一切?
这是平面列表代码:
<FlatList
data=recados
onRefresh=getRecados
refreshing=refreshing
showsVerticalScrollIndicator=false
renderItem=( item ) => (
<Card
texto=item.texto
titulo=item.titulo
timestamp=item.timestamp
info1=item.remetente
info2=
"ao " + item.ano_dest + "º " + item.curso_dest + " " + item.turno_dest
/>
)
/>;
【问题讨论】:
还有一些会导致问题的代码。比如你使用了 await 和 then,这会给你带来 promise 的问题。 @Ashish 我无法删除异步,因为如果没有等待,代码的 firebase 部分将无法工作。 您必须使用async/await
或promise/then
。您可以在函数中同时使用这两种方式。
@Ashish 我试图将 getRecados 变成一个承诺,但正如我所说,我必须在从 firebase 查询时使用 await 关键字,所以我最终遇到了问题,因为我不能在承诺中使用 await
@PriyashreeBhadra 我已经解决了这个问题,刚刚发布了一个答案来解释我是如何做到的。
【参考方案1】:
如果您调试代码,您可能会发现在将数据设置为 Recados 之前关闭加载。
而是在停止加载之前将数据设置为Recados
。
const getRecados = async () =>
setRefreshing(true)
try
const recadosRef = firebase.firestore().collection('recados');
const records = await recadosRef.orderBy('timestamp', 'desc').get();
if(records == undefined)
Alert.alert("Erro ao consultar os recados!!!", err.message);
const recadosList = new Array();
if (user_setor.length == 0)
records.forEach(doc =>
if ((doc.data().curso_dest == user_curso
|| doc.data().curso_dest == '')
&& (doc.data().ano_dest == user_ano
|| doc.data().ano_dest == '')
&& (doc.data().turno_dest == user_turno
|| doc.data().turno_dest == ''))
recadosList.push(doc)
)
else
records.forEach(doc =>
if (user_setor.includes(doc.data().remetente))
recadosList.push(doc)
)
setFullData(recadosList.map((doc) => (
id: doc.id,
titulo: doc.data().titulo,
timestamp: doc.data().timestamp,
remetente: doc.data().remetente,
curso_dest: doc.data().curso_dest,
ano_dest: doc.data().ano_dest,
turno_dest: doc.data().turno_dest,
texto: doc.data().texto
)));
setRecados(fullData)
setLoading(false)
catch (err)
Alert.alert("Erro ao consultar os recados!!!", err.message);
setRefreshing(false)
;
如果您使用async/await
代码应该是这样的
【讨论】:
它没有帮助,我实际上认为加载没有做任何事情,它被声明为 useState(true) 一次,然后在 getRecados 中设置为 false,这实际上是它的唯一两次提到了,但不是我添加的,所以我害怕删除它。 @gralmeidan 检查更新代码【参考方案2】:只有一个条件是在您的 api 调用完成之前不显示FlatList
。您已经在管理 loading
变量,因此请仅使用它
if(loading)
// Show loader or actvityIndicator
else
// Your flat list code.
【讨论】:
现在它会在显示空的平面列表之前做一些加载动画 是的,这是正确的方法吗?直到我们有数据显示加载器 问题是我们确实有数据,flatlist 是空的,因为由于某种原因它在存储数据的状态可以更新之前一直渲染 FlatList 无论如何都会在我们加载该组件后立即渲染,我们无法阻止它。我不明白你说“我们确实有数据”的意思。这是否意味着在调用 api 之前,您的状态变量中就有数据?【参考方案3】:我尝试了 Ashish 提出的使用 Promise/Then
而不是 Async/Await
的建议,它有点奏效了,使用 .get().then()
确实解决了数据未在 useEffect 上加载的问题,但它只加载了 4由于某种原因,我在 firebase 上拥有的 15 个文档中,所以对我有用的是使用 firebase 的 .onSnapshot()
函数 insted of .get()
,这是生成的代码:
const getRecados = async () =>
setRefreshing(true);
try
const recadosRecebidos = firebase
.firestore()
.collection("recados")
.orderBy("timestamp", "desc")
.onSnapshot(
snapshot =>
/*
* Just filtering the data, has nothing to do with the problem;
*/
return result
, []);
setFullData(recadosList);
setRecados(recadosList);
,
() =>
setError(true);
);
setLoading(false);
catch (err)
Alert.alert("Erro ao consultar os recados!!!", err.message);
setRefreshing(false);
;
【讨论】:
以上是关于我的 flatList 在我的 api 查询完成之前呈现的主要内容,如果未能解决你的问题,请参考以下文章
我编写了用于在反应中列出书籍的代码,但 FlatList 在我的代码中不起作用,我该如何解决?
在 FlatList React Native 中仅显示 10 条记录