英文:
React Native and FIrebase: Making an async call seems to run through twice
问题
在继续处理我的问题时,我有一个有点令人困惑的问题。我的应用程序有两个互相交互的JS文件,但奇怪的是,当我调用从Firestore获取数据的函数时,它似乎想要运行两次。
这是HomeScreen.js文件,它应该调用UserInformation:
import { Pressable, Text } from 'react-native';
import { useEffect, useState } from 'react';
import { FlatList } from 'react-native-gesture-handler';
import { getStorage, ref, getDownloadURL } from 'firebase/storage';
// 导入用户信息组件
import UserInformation from '../components/UserInformation';
import ClubInformation from '../components/ClubInformation';
import AircraftInformation from '../components/AircraftInformation';
function HomeScreen() {
const userDetails = UserInformation();
const clubDetails = ClubInformation();
const aircraftDetails = AircraftInformation();
if (userDetails !== null) {
//console.log(userDetails)
//console.log(clubDetails)
//console.log(aircraftDetails)
}
if (!userDetails) {
return <Text>Loading...</Text>;
}
if (!clubDetails) {
return <Text>Loading...</Text>;
}
return (
<Text>
Welcome {userDetails.first} {userDetails.last} {clubDetails.name}! This is a placeholder for future updates in the home screen
</Text>
);
}
export default HomeScreen;
下面是userInformation.js中的userDetails调用:
import { useState, useEffect } from "react";
import { getAuth } from "firebase/auth";
import { doc, getDoc } from "firebase/firestore";
import { db } from '../components/FirebaseConfig';
export default function UserInformation() {
const [userDetails, setUserDetails] = useState(null);
useEffect(() => {
async function getUserDetails() {
const user = getAuth().currentUser;
const userRef = doc(db, "users", user.uid);
const docSnap = await getDoc(userRef);
if (docSnap.exists()) {
const data = docSnap.data();
setUserDetails(data);
} else {
console.log("No such User!");
}
}
getUserDetails();
}, []);
return userDetails;
}
每当我在HomeScreen中执行控制台日志时,它似乎首先返回null,然后返回数据。这里是否有什么问题(我肯定是有问题的),还是这是标准行为?在此先感谢您。
我尝试以多种方式运行它,但那些也查询数据库的其他函数似乎也会出现相同的情况。我不知道是否与我的异步操作有关。
英文:
as I continue to work on my issues I've got one that's kind of perplexing. my app has two JS files that interact with each other, but what's odd is it seems that then I call the function to get the data from firestore it seems that it wants to run it twice.
Here is the HomeScreen.js file that is suppoed to call UserInformation
import { Pressable, Text } from 'react-native';
import { useEffect, useId, useState } from 'react';
import { async } from '@firebase/util';
import { FlatList } from 'react-native-gesture-handler';
import {getStorage, ref, getDownloadURL} from 'firebase/storage';
//import the user infomration component
import UserInformation from '../components/UserInformation';
import ClubInformation from '../components/ClubInformation';
import AircraftInformation from '../components/AircraftInformation';
function HomeScreen() {
const userDetails = UserInformation();
const clubDetails = ClubInformation();
const aircraftDetails = AircraftInformation();
if (userDetails !== null) {
//console.log(userDetails)
//console.log(clubDetails)
//console.log(aircraftDetails)
}
if(!userDetails) {
return <Text>Loading...</Text>
}
if(!clubDetails) {
return <Text>Loading...</Text>
}
return <Text>Welcome {userDetails.first} {userDetails.last} {clubDetails.name}! This is a placeholder for future updates in the home screen</Text>
}
export default HomeScreen
the userDetails calls is below:
userInformation.js
import { useState, useEffect } from "react";
import { getAuth } from "firebase/auth";
import { doc, getDoc } from "firebase/firestore";
import { db } from '../components/FirebaseConfig';
export default function UserInformation() {
const [userDetails, setUserDetails] = useState(null);
useEffect(() => {
async function getUserDetails() {
const user = getAuth().currentUser;
const userRef = doc(db, "users", user.uid);
const docSnap = await getDoc(userRef);
if (docSnap.exists()) {
const data = docSnap.data();
setUserDetails(data);
} else {
console.log("No such User!");
}
}
getUserDetails();
}, []);
return userDetails;
}
Whenever I do a console log from the HomeScreen it seems to first return null, then it returns the data. Is there something I'm doing wrong here (I'm sure it is) or is it standard behavior? Thank you in advance
I tried to run this multiple ways but those other functions that i have that also query the db seem to do the same thing. I don't know if it's something up with my async
答案1
得分: 2
这是UserInformation
函数作为自定义钩子工作时的预期行为。
当首次初始化/挂载HomeScreen
组件时,userDetails
的默认值是null
。
几秒钟后,应用程序从Firestore获取数据并更新userDetails
状态值,触发第二次重新渲染。
注意:建议的最佳实践是始终以use[FUNCTION_NAME]的方式命名自定义钩子函数,例如useUserInformation。
英文:
This is expected behavior when UserInformation
function is working as a custom hook.
The first time when HomeScreen
component was initialized/mounted, the default value userDetails
is null
.
After a few seconds, the app fetches data from Firestore and updates userDetails
state value which trigger a second rerender.
Note: Recommended best practice is always prefixed custom hooks function name use[FUNCTION_NAME] like useUserInformation.
答案2
得分: 1
你的逻辑完全错误。你不需要等待引用钩子函数。即使你想获得有效的响应,你也可以使用useEffect
钩子。
function HomeScreen() {
const userDetails = UserInformation();
const clubDetails = ClubInformation();
const aircraftDetails = AircraftInformation();
useEffect(() => {
if (userDetails) {
console.log(userDetails);
}
}, [userDetails]);
if (!userDetails) {
return <Text>Loading...</Text>;
}
if (!clubDetails) {
return <Text>Loading...</Text>;
}
return <Text>Welcome {userDetails.first} {userDetails.last} {clubDetails.name}! This is a placeholder for future updates in the home screen</Text>;
}
正如我在评论中所说,你不需要创建自定义的钩子函数。使用普通函数就足够了,它会像这样工作。
async function getUserDetails() {
const user = getAuth().currentUser;
const userRef = doc(db, "users", user.uid);
const docSnap = await getDoc(userRef);
if (docSnap.exists()) {
const data = docSnap.data();
return data;
} else {
console.log("No such User!");
return null;
}
}
function HomeScreen() {
const [userDetails, setUserDetails] = useState(null);
useEffect(() => {
getUserDetails().then(data => {
if (data !== null) {
setUserDetails(data);
}
});
}, []);
if (!userDetails) {
return <Text>Loading...</Text>;
}
return <Text>Welcome {userDetails.first} {userDetails.last}</Text>;
}
英文:
Your logic is completely wrong. You couldn't wait on referencing hook function.
Even you can use useEffect hook if you want to get valid response.
function HomeScreen() {
const userDetails = UserInformation();
const clubDetails = ClubInformation();
const aircraftDetails = AircraftInformation();
useEffect(()=>{
if (userDetails) {
console.log(userDetails)
}
}, [userDetails])
if(!userDetails) {
return <Text>Loading...</Text>
}
if(!clubDetails) {
return <Text>Loading...</Text>
}
return <Text>Welcome {userDetails.first} {userDetails.last} {clubDetails.name}! This is a placeholder for future updates in the home screen</Text>
}
As I said in my comment you don't need to create your custom hook functions. It's enough with normal functions it will work like this.
async function getUserDetails() {
const user = getAuth().currentUser;
const userRef = doc(db, "users", user.uid);
const docSnap = await getDoc(userRef);
if (docSnap.exists()) {
const data = docSnap.data();
return data;
} else {
console.log("No such User!");
return null
}
}
function HomeScreen() {
const [userDetails, setUserDetails] = useState(null)
useEffect(()=>{
getUserDetails().then(data=>{
if (data != null) {
setUserDetails(data)
}
})
}, [])
if (!userDetails) {
return <Text>Loading...</Text>
}
return <Text>Welcome {userDetails.first} {userDetails.last}</Text>
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论