React Native 和 Firebase:进行异步调用似乎运行了两次。

huangapple go评论55阅读模式
英文:

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 &#39;react-native&#39;;

import { useEffect, useId, useState } from &#39;react&#39;;
import { async } from &#39;@firebase/util&#39;;
import { FlatList } from &#39;react-native-gesture-handler&#39;;
import {getStorage, ref, getDownloadURL} from &#39;firebase/storage&#39;;
//import the user infomration component
import UserInformation from &#39;../components/UserInformation&#39;;
import ClubInformation from &#39;../components/ClubInformation&#39;;
import AircraftInformation from &#39;../components/AircraftInformation&#39;;



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 &lt;Text&gt;Loading...&lt;/Text&gt;
}

if(!clubDetails) {
	return &lt;Text&gt;Loading...&lt;/Text&gt;
}
	
	return &lt;Text&gt;Welcome {userDetails.first} {userDetails.last} {clubDetails.name}!  This is a placeholder for future updates in the home screen&lt;/Text&gt;




}

export default HomeScreen

the userDetails calls is below:
userInformation.js

import { useState, useEffect } from &quot;react&quot;;
import { getAuth } from &quot;firebase/auth&quot;;
import { doc, getDoc } from &quot;firebase/firestore&quot;;
import { db } from &#39;../components/FirebaseConfig&#39;;

export default function UserInformation() {
    const [userDetails, setUserDetails] = useState(null);
    
    useEffect(() =&gt; {
        async function getUserDetails() {
        const user = getAuth().currentUser;
        const userRef = doc(db, &quot;users&quot;, user.uid);
        const docSnap = await getDoc(userRef);
        if (docSnap.exists()) {
            const data = docSnap.data();
            setUserDetails(data);
        } else {
            console.log(&quot;No such User!&quot;);
        }
        }
        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(()=&gt;{
  if (userDetails) {
    console.log(userDetails)
  }
}, [userDetails])

if(!userDetails) {  
    return &lt;Text&gt;Loading...&lt;/Text&gt;
}

if(!clubDetails) {
    return &lt;Text&gt;Loading...&lt;/Text&gt;
}
    
    return &lt;Text&gt;Welcome {userDetails.first} {userDetails.last} {clubDetails.name}!  This is a placeholder for future updates in the home screen&lt;/Text&gt;




}

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, &quot;users&quot;, user.uid);
    const docSnap = await getDoc(userRef);
    if (docSnap.exists()) {
        const data = docSnap.data();
        return data;
    } else {
        console.log(&quot;No such User!&quot;);
        return null
    }
}

function HomeScreen() {
    const [userDetails, setUserDetails] = useState(null)
    useEffect(()=&gt;{
        getUserDetails().then(data=&gt;{
            if (data != null) {
                setUserDetails(data)
            }
        })
    }, [])
    if (!userDetails) {  
        return &lt;Text&gt;Loading...&lt;/Text&gt;
    }
    return &lt;Text&gt;Welcome {userDetails.first} {userDetails.last}&lt;/Text&gt;
}

huangapple
  • 本文由 发表于 2023年2月18日 14:02:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75491505.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定