【问题标题】:React native useEffect render problem when trying to get user's auth state firebase尝试获取用户的身份验证状态firebase时反应本机useEffect渲染问题
【发布时间】:2021-07-30 14:09:35
【问题描述】:

我对 useEffect 有疑问。当我尝试在onAuthStateChanged 之后获取用户的身份验证状态时,useEffect 中的调用次数非常高。有时它也会给出这个错误:

警告:无法对未安装的组件执行 React 状态更新。这是一个无操作,但表明您的应用程序中存在内存泄漏。要修复,请在 useEffect 清理函数中取消所有订阅和异步任务

This is the amount of logs after the user login/registers and logout。也许我不太了解 useEffect 是如何工作的。这是使用useEffect的代码:

useEffect(async () => {
    let isCancelled = false;
    await firebase.auth().onAuthStateChanged(async (user) => {
      if (user && !isCancelled) {
          await firebase
          .firestore()
          .collection('users')
          .doc(user.uid)
          .get()
          .then((document) => {
            const userData = document.data()
            console.log(document.data())
            setUser(userData);
            setIsSignedIn(true);
            setLoading(false);
          })
          .catch((error) => {
            setLoading(false);
            alert(error)
          });
        }else{
          console.log('user does not exist')
          setIsSignedIn(false);
          setLoading(false);
        }
    });
    return () => {
      isCancelled = true;
    }
  }, []);

This is the image of it. Maybe it's more clear

【问题讨论】:

    标签: reactjs firebase react-native firebase-authentication use-effect


    【解决方案1】:

    一般来说,每个useEffect 应该负责一项任务。此外,当前使用 isCancelled 的方法实际上并没有像应有的那样清理侦听器。

    对于反应,您应该尽可能使用实时更新。您还将受益于能够轻松分离侦听器。

    这是一个你可以使用的脚手架。

    // Set up a state variable to contain the user's info
    // If a user is already logged in and validated, user is immediately
    // set to their User object, otherwise show loading icon while we check
    const [user, setUser] = useState(() => firebase.auth().currentUser || undefined);
    const userLoading = user === undefined;
    const isSignedIn = !!user;
    
    // Set up a state variable to contain the user's data
    const [userData, setUserData] = useState(undefined);
    
    // Set up a state variable to contain whether this component is loading
    const [loading, setLoading] = useState(true);
    
    // effect to track user state and update `user` for any changes
    // onAuthStateChanged returns its own cleanup function
    useEffect(() => firebase.auth().onAuthStateChanged(setUser), []); // <- don't rerun
    
    // effect to navigate to login
    useEffect(() => {
      if (user === null) {
        // user is signed out
        navigation.navigate('login');
      }
    }, [user]); // <- rerun when user changes
    
    useEffect(async () => {
      if (!isSignedIn) return; // you could write this as `userLoading || !isSignedIn`, but it's redundant
    
      return firebase.firestore()
        .collection('users')
        .doc(user.uid)
        .onSnapshot({ // <- onSnapshot() returns its own cleanup function
          next(docSnapshot) {
            const userData = docSnapshot.data();
            setUserData(userData);
          },
          error(err) {
            console.error(err);
            alert(err);
          }
        });
    }, [user]); // <- rerun when user changes
    

    作为一个学习项目,可以考虑将其制成Context 或创建您自己的useAuth 函数,您可以在其中提取用户数据、用户对象和加载状态。

    【讨论】:

    • 感谢您的回答,我正在努力让它工作,但我做不到
    • 具体是什么不起作用?仅仅说它不起作用并不能提供足够的信息。
    • 当我按下注册按钮时,用户被注册并且他的信息被保存在 firebase 的 Authentication 字段中,但是用户数据不在 firestore 所以当用户的身份验证状态在注册后,他试图在没有任何数据的情况下进入 HomeScreen。我可能以错误的方式使用 useEffect 。如果你愿意,我可以编辑我的问题,添加导航和注册的完整代码
    • @tedofrenci 此处的代码专门处理在用户按照您的要求登录/完成注册后读取数据并包含在您的问题中。在用户登录后,此代码不处理任何导航等,因为您没有询问。如果您在应用此修复后遇到登录流程问题,请针对新代码和问题提出新问题。
    【解决方案2】:

    试试这个

    useEffect(async () => {
        let isCancelled = false;
        const unsubscribe = await firebase.auth().onAuthStateChanged(async (user) => {
           ........ 
        });
        return () => {
          // cleanup 
         unsubscribe() 
          isCancelled = true;
        }
      }, []);
    

    让我知道它是否对你有用

    【讨论】:

      猜你喜欢
      • 2020-12-13
      • 2022-12-08
      • 2016-04-07
      • 2020-12-22
      • 1970-01-01
      • 2018-09-11
      • 2017-12-25
      • 2023-03-13
      • 2022-01-21
      相关资源
      最近更新 更多