获取数据时 React-Native 加载状态不更新
React-Native loading state not updating when fetching data
我遇到这个问题已经有一段时间了,我尝试了所有我能想到的方法,但到目前为止我还没有找到解决这个问题的办法。从我的数据库中获取数据时,我将加载状态设置为 true,完成后我将其设置回 false,现在的问题是它永远不会设置为 true。在代码示例中,我将获取延迟了 5 秒,以便它模拟慢速互联网以查看加载指示器和状态更改(如果它可以工作)。
编辑:我正在使用 firebase firestore 获取我的数据。更具体地说,我使用非异步的 onsnapshot 监听器,所以我不能使用异步。我还删除了 try-catch 块,因为它也没有用,但在调用数据库之前加载状态仍未设置为 true。
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
try {
setTimeout(() => {
//fetchting from database.
}, 5000);
return () => {
/* unsubscribe(); */
};
} catch (error) {
console.log(error);
} finally {
setLoading(false);
}
}, []);
编辑函数:
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
setTimeout(() => {
firebase.db
.collection("collectionname")
.onSnapshot((snapshot) => {
//handeling data returned.
})},
5000
);
setLoading(false);
return () => {
/* unsubscribe(); */
};
}, []);
问题是 setLoading(false)
将在数据(等待 5 秒)具有 运行 之前被调用。在这里,您可以 await
等待 5 秒的 Promise
(在生产中您将使用 fetch
或类似的)。现在,finally
块不会 运行 直到 在 承诺解决之后。
const [loading, setLoading] = useState(true);
useEffect(() => {
const getData = async () => {
try {
// get data (waiting 5 seconds for example)
// note `await` - the `finally` won't run until after this has resolved
await new Promise(res => setTimeout(res, 5000))
return () => {
// unsubscribe()
}
} catch (error) {
console.error(error)
} finally {
setLoading(false)
}
}
getData()
}, []);
编辑:由于您是通过回调获取数据的,因此您需要将其包装在一个承诺中,这样您就可以 await
它,就像这样:
useEffect(() => {
const getData = async () => {
try {
const snapshot = await new Promise(resolve =>
firebase.db
.collection("collectionname")
.onSnapshot(resolve)
)
return () => {
// unsubscribe()
}
} catch (error) {
console.error(error)
} finally {
setLoading(false)
}
}
getData()
}, []);
您的代码如何执行在这里很重要。您的第一个 setLoading
运行并设置为 true
。然后,您的 setTimeout
被 初始化 但是(这就是问题所在)在您的 setTimeout
命令初始化之后,立即调用 setLoading
再次设置为 false,因为 setTimeout
初始化后没有中断。因此,加载在您的数据库被调用之前设置为 true,但由于您的代码的执行顺序,它会在任何事情有机会发生之前立即设置为 false。
尝试在 setTimeout 内设置您的 setLoading(false)
,如下所示:
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
setTimeout(() => {
firebase.db
.collection("collectionname")
.onSnapshot((snapshot) => {
//handeling data returned.
});
//moved setLoading to within final setTimeout execution
setLoading(false);
},
5000
);
return () => {
/* unsubscribe(); */
};
}, []);
我遇到这个问题已经有一段时间了,我尝试了所有我能想到的方法,但到目前为止我还没有找到解决这个问题的办法。从我的数据库中获取数据时,我将加载状态设置为 true,完成后我将其设置回 false,现在的问题是它永远不会设置为 true。在代码示例中,我将获取延迟了 5 秒,以便它模拟慢速互联网以查看加载指示器和状态更改(如果它可以工作)。
编辑:我正在使用 firebase firestore 获取我的数据。更具体地说,我使用非异步的 onsnapshot 监听器,所以我不能使用异步。我还删除了 try-catch 块,因为它也没有用,但在调用数据库之前加载状态仍未设置为 true。
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
try {
setTimeout(() => {
//fetchting from database.
}, 5000);
return () => {
/* unsubscribe(); */
};
} catch (error) {
console.log(error);
} finally {
setLoading(false);
}
}, []);
编辑函数:
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
setTimeout(() => {
firebase.db
.collection("collectionname")
.onSnapshot((snapshot) => {
//handeling data returned.
})},
5000
);
setLoading(false);
return () => {
/* unsubscribe(); */
};
}, []);
问题是 setLoading(false)
将在数据(等待 5 秒)具有 运行 之前被调用。在这里,您可以 await
等待 5 秒的 Promise
(在生产中您将使用 fetch
或类似的)。现在,finally
块不会 运行 直到 在 承诺解决之后。
const [loading, setLoading] = useState(true);
useEffect(() => {
const getData = async () => {
try {
// get data (waiting 5 seconds for example)
// note `await` - the `finally` won't run until after this has resolved
await new Promise(res => setTimeout(res, 5000))
return () => {
// unsubscribe()
}
} catch (error) {
console.error(error)
} finally {
setLoading(false)
}
}
getData()
}, []);
编辑:由于您是通过回调获取数据的,因此您需要将其包装在一个承诺中,这样您就可以 await
它,就像这样:
useEffect(() => {
const getData = async () => {
try {
const snapshot = await new Promise(resolve =>
firebase.db
.collection("collectionname")
.onSnapshot(resolve)
)
return () => {
// unsubscribe()
}
} catch (error) {
console.error(error)
} finally {
setLoading(false)
}
}
getData()
}, []);
您的代码如何执行在这里很重要。您的第一个 setLoading
运行并设置为 true
。然后,您的 setTimeout
被 初始化 但是(这就是问题所在)在您的 setTimeout
命令初始化之后,立即调用 setLoading
再次设置为 false,因为 setTimeout
初始化后没有中断。因此,加载在您的数据库被调用之前设置为 true,但由于您的代码的执行顺序,它会在任何事情有机会发生之前立即设置为 false。
尝试在 setTimeout 内设置您的 setLoading(false)
,如下所示:
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
setTimeout(() => {
firebase.db
.collection("collectionname")
.onSnapshot((snapshot) => {
//handeling data returned.
});
//moved setLoading to within final setTimeout execution
setLoading(false);
},
5000
);
return () => {
/* unsubscribe(); */
};
}, []);