react-native-firebase icon indicating copy to clipboard operation
react-native-firebase copied to clipboard

[🐛] Androind - onAuthStateChanged does not fire when I refresh the app from the metro teminal by pressing R

Open mehtaanirudh opened this issue 1 year ago • 1 comments

Issue

So auth.onAuthStateChanged() works fine when I open the app in emulator. However, when I press R on the metro terminal the app reloads but auth.onAuthStateChanged() does not fire. It works fine for iOS.

Is this an expected behaviour? I am using react native CLI

My versions are -

"@react-native-firebase/app": "^20.0.0", "@react-native-firebase/auth": "^20.0.0", "react": "18.2.0", "react-native": "0.74.1"

My JS:

import { View, Text } from 'react-native';
import auth from '@react-native-firebase/auth';


function App() {
  // Set an initializing state whilst Firebase connects
  const [initializing, setInitializing] = useState(true);
  const [user, setUser] = useState();

  // Handle user state changes
  async function onAuthStateChanged(user) {
    setUser(user);
    if (initializing) setInitializing(false);
  }


  useEffect(() => {
    const subscriber = auth().onAuthStateChanged(onAuthStateChanged);
    if (auth().currentUser) {
      onAuthStateChanged(auth().currentUser);
    }
    return subscriber; // unsubscribe on unmount
  }, []);

  if (initializing)  return (
    <View>
      <Text>Loading</Text>
    </View>
  );

  if (!user) {
    return (
      <View>
        <Text>Login</Text>
      </View>
    );
  }

  return (
    <View>
      <Text>Welcome {user.email}</Text>
    </View>
  );
}

export default App;

Closing and reopening the app shows Login but when I press R I see Loading only

mehtaanirudh avatar Jun 01 '24 22:06 mehtaanirudh

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

github-actions[bot] avatar Jun 29 '24 23:06 github-actions[bot]

Experiencing the same thing in an Expo managed project.

"expo": "51.0.20" "@react-native-firebase/app": "^20.1.0" "@react-native-firebase/auth": "^20.1.0" "react": "18.2.0" "react-native": "0.74.2"

wneild avatar Jul 16 '24 12:07 wneild

Facing the same issue. Using Expo SDK 51.

"expo": "~51.0.28 "@react-native-firebase/app": "^20.4.0" "@react-native-firebase/auth": "^20.4.0" "react-native": "0.74.5"

vm02 avatar Aug 19 '24 14:08 vm02

Same here with

"expo": "~51.0.18",
"@react-native-firebase/app": "^20.1.0",
"@react-native-firebase/auth": "^20.1.0",
"react-native": "0.74.3",

enlob avatar Aug 23 '24 14:08 enlob

Facile the same in expo 51, it used to work well before upgrading to :

"expo": "~51.0.31", "@react-native-firebase/app": "^18.9.0", "@react-native-firebase/auth": "^18.9.0", "react-native": "0.74.5",

NicolasMarcinkowski avatar Sep 16 '24 13:09 NicolasMarcinkowski

Same, fresh install. iOS working fine. Android first load works, press R in terminal to refresh and onAuthStateChanged is never entered.

devpascoe avatar Sep 29 '24 15:09 devpascoe

Same here but without expo "@react-native-firebase/app": "^21.0.0", "@react-native-firebase/auth": "^21.0.0",

RANGELJ avatar Oct 04 '24 00:10 RANGELJ

same, onAuthStateChange not work when i press R

    "expo": "~51.0.28",
    "@react-native-firebase/app": "^21.2.0",
    "@react-native-firebase/auth": "^21.2.0",
    "@react-native-firebase/firestore": "^21.2.0",

horacio-a avatar Nov 12 '24 21:11 horacio-a

i am also facing the same issue "@react-native-firebase/app": "^21.2.0", "@react-native-firebase/auth": "^21.2.0", "@react-native-firebase/messaging": "^21.2.0", "@react-native-firebase/storage": "^21.2.0" @mikehardy can we get a answer on this part please ?

CodeWithBlaze avatar Nov 15 '24 07:11 CodeWithBlaze

Hmm - do you see this log tag in adb logcat?

https://github.com/invertase/react-native-firebase/blob/789d41b842e0726b47cc919ab1a8bedc4e4a9b44/packages/auth/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java#L128

And then after do you see any of these re-registering? https://github.com/invertase/react-native-firebase/blob/789d41b842e0726b47cc919ab1a8bedc4e4a9b44/packages/auth/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java#L182

Curious what react-native version and style (new architecture or old architecture) people are running that are seeing this?

Because react-native-firebase still needs to forward-port to invalidate and away from onCatalystInstanceDestroy, regardless of this issue, though it may be related to this issue

mikehardy avatar Nov 15 '24 15:11 mikehardy

hey @mikehardy i can provide you info on what react native version i am using, React Native -> 0.76.1 ->new architecture

and to answer your above question on refresh also i didn't see this log "instance-destroyed" but for the first time i can see this "addAuthStateListener"

Here is what i got from adb logcat

2024-11-15 22:08:07.050 4658-4856 Auth com.habitat D instance-initialized 2024-11-15 22:08:07.211 4658-4857 Auth com.habitat D addAuthStateListener 2024-11-15 22:08:07.213 4658-4857 Auth com.habitat D addIdTokenListener 2024-11-15 22:08:07.215 4658-4658 Auth com.habitat D addAuthStateListener:eventBody {"appName":"[DEFAULT]"} 2024-11-15 22:08:07.218 4658-4857 Auth com.habitat D configureAuthDomain 2024-11-15 22:08:07.219 4658-4857 Auth com.habitat D configureAuthDomain - app [DEFAULT] domain? null

this is how i use it useLayoutEffect(()=>{ Appearance.setColorScheme("light") const subscriber = auth().onAuthStateChanged(onAuthStateChanged); return subscriber; // unsubscribe on unmount },[])

CodeWithBlaze avatar Nov 15 '24 16:11 CodeWithBlaze

I just tried react-native 0.76.2 and react-native-firebase 21.4.0 from make-demo.sh against the firebase emulator auth instance and I was unable to reproduce. I double-tap r on the device, and I get listener activity for onAuthStateChanged before and after reload.

Start with this https://github.com/mikehardy/rnfbdemo/blob/main/make-demo.sh

Apply this diff to App.tsx for testing

mike@kunashir:~/work/Invertase/rnfbdemo (main *) % git diff

diff --git a/App.tsx b/App.tsx
index 69e2500..48b231b 100644
--- a/App.tsx
+++ b/App.tsx
@@ -8,6 +8,7 @@
 import React from 'react';
 import type {PropsWithChildren} from 'react';
 import {
+  Button,
   SafeAreaView,
   ScrollView,
   StatusBar,
@@ -23,7 +24,7 @@ import firebase from '@react-native-firebase/app';
 import analytics from '@react-native-firebase/analytics';
 import appCheck from '@react-native-firebase/app-check';
 import appDistribution from '@react-native-firebase/app-distribution';
-import auth from '@react-native-firebase/auth';
+import auth, { FirebaseAuthTypes } from '@react-native-firebase/auth';
 import crashlytics from '@react-native-firebase/crashlytics';
 import database from '@react-native-firebase/database';
 import dynamicLinks from '@react-native-firebase/dynamic-links';
@@ -79,6 +80,12 @@ function App(): JSX.Element {
     },
   });
 
+  firebase.auth().useEmulator('http://localhost:9099');
+
+  firebase.auth().onAuthStateChanged((user) => {
+    console.log('onAuthStateChanged was called with user ' + user);
+  });
+
   return (
     <SafeAreaView style={backgroundStyle}>
       <StatusBar
@@ -88,6 +95,8 @@ function App(): JSX.Element {
       <ScrollView
         contentInsetAdjustmentBehavior="automatic"
         style={backgroundStyle}>
+          <Button title="sign in" onPress={async () => { console.log('anonymous sign in '); await firebase.auth().signInAnonymously()}} />
+          <Button title="sign out" onPress={async () => { console.log('signing out'); await firebase.auth().signOut(); }} />
         <View
           style={{
             backgroundColor: isDarkMode ? Colors.black : Colors.white,

mikehardy avatar Nov 15 '24 16:11 mikehardy

perhaps the effect you are using is not firing on reload? I'm not sure, but at least if you just register the listener at app startup every time (as you should do with something as basic as your event listeners?) it would work ?

mikehardy avatar Nov 15 '24 16:11 mikehardy

the effect is atually firing. i have added console.log to see it, it is even reaching auth() but then i don't know why is it not firing

CodeWithBlaze avatar Nov 15 '24 17:11 CodeWithBlaze

Note I linked a PR here that has a title indicating it might fix this, it will not. The "fix" in that PR is to correctly teardown on hot reload as the react host goes away - it has nothing to do with setup. So it shouldn't have bearing on this issue but I noticed it while looking into this one

mikehardy avatar Nov 15 '24 19:11 mikehardy

I will tell you what is exactly happening and you can confirm if it is with reloading.

While doing the process below at no time will we signin the user so user will always be null.

When the app loads for the first time, everything works as expected i.e onAuthStateChanged Listener fires up with user = null.

Now the app is loaded.

Then we do not do anything and just press R (do not signin the user) on the metro terminal and it reloads.

As per your checks I get the log instance-initialize and addAuthStateListener

addAuthStateListener with event-body do not fire And finally the function do not fire.

So is it supposed to be like this that since there is no change in auth state after reload it will not fire again. Is it something like that.

Also I am not very familiar with native code so do not know how invariant is related to hot-reloading.

If you need any other info I can provide I will also test it on a new app to create a reproducer if possible

CodeWithBlaze avatar Nov 16 '24 03:11 CodeWithBlaze

If you don't change the user you won't see a handler called, and hot reloading doesn't change the user, so no handler called.

This is as expected.

As you signInAnonymously (or some other way, for testing) and signOut, you'll see the listener called, because now the user is changing. And for me at least, that continued to happen even after a reload, so I couldn't reproduce what the issue alleged - "onAuthStateChanged does not fire when I refresh the app from the metro terminal by pressing R". Well it doesn't fire immediately but the listener isn't dead or anything, it will fire when there are changes. That should be sufficient?

mikehardy avatar Nov 16 '24 03:11 mikehardy

Hey @mikehardy . First of all thank you for the clarification and thank you for all of your time. the thing is I have one of my app that is on react native 0.73.1 and it uses "@react-native-firebase/app": "^18.7.3", "@react-native-firebase/auth": "^18.7.3", "@react-native-firebase/messaging": "^18.8.0", "@react-native-firebase/storage": "^18.7.3",

in this case the onAuthStateListener fires up with user null everytime i reload even when i do not change any state

LOG base url: http://192.168.1.2:8000 LOG env : development LOG user null

info Reloading connected app(s)... BUNDLE ./index.js LOG user null LOG base url: http://192.168.1.2:8000 LOG env : development

is this behaviour changed in the new architecture or am i missing something here ?

CodeWithBlaze avatar Nov 16 '24 04:11 CodeWithBlaze

I've been using this library for years it's def a new (and unwanted) behavior because then idk what the user state is after app startup if this handler never gets called. Not called = potentially still intializing, called with null = initialized and actually not signed in

-------- Original Message -------- On 11/16/24 8:00 AM, Sagnik wrote:

Hey @.(https://github.com/mikehardy) . First of all thank you for the clarification and thank you for all of your time. the thing is I have one of my app that is on react native 0.73.1 and it uses @./app": "^18.7.3", @./auth": "^18.7.3", @./messaging": "^18.8.0", @.***/storage": "^18.7.3",

in this case the onAuthStateListener fires up with user null everytime i reload even when i do not change any state

LOG base url: http://192.168.1.2:8000 LOG env : development LOG user null

info Reloading connected app(s)... BUNDLE ./index.js LOG user null LOG base url: http://192.168.1.2:8000 LOG env : development

is this behaviour changed in the new architecture or am i missing something here ?

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.***>

MicroDroid avatar Nov 16 '24 04:11 MicroDroid

I see - thanks for the clarification that it was really focused on that initial state update, I did not have that clear in my mind, and honestly didn't really understand that part of this listeners feature set until you clarified that

In that case, the bug I fixed yesterday with #8139 really did fix this, and I confirm it by using the patches from the PR here: https://github.com/invertase/react-native-firebase/actions/runs/11862072310

11-16 10:37:46.306  9570  9694 D Auth    : addIdTokenListener
11-16 10:37:46.306  9570  9694 D Auth    : configureAuthDomain
11-16 10:37:46.306  9570  9694 D Auth    : configureAuthDomain - app [DEFAULT] domain? null
11-16 10:37:46.307  9570  9570 D Auth    : addAuthStateListener:eventBody {"appName":"[DEFAULT]"}
11-16 10:37:46.414  9570  9693 I ReactNativeJS: onAuthStateChanged was called with user null

(I did a hot reload here)

11-16 10:37:52.184  9570  9665 D Auth    : instance-destroyed.  // <-- This line is new with the patches!
11-16 10:37:52.817  9570  9724 D Auth    : instance-initialized
11-16 10:37:52.822  9570  9725 D Auth    : addAuthStateListener
11-16 10:37:52.822  9570  9725 D Auth    : addIdTokenListener
11-16 10:37:52.822  9570  9725 D Auth    : configureAuthDomain
11-16 10:37:52.822  9570  9725 D Auth    : configureAuthDomain - app [DEFAULT] domain? null
11-16 10:37:52.822  9570  9724 I ReactNativeJS: Mapping auth host "localhost" to "10.0.2.2" for android emulators. Use real IP on real devices. You can bypass this behaviour with "android_bypass_emulator_url_remap" flag.
11-16 10:37:52.822  9570  9570 D Auth    : addAuthStateListener:eventBody {"appName":"[DEFAULT]"}
11-16 10:37:52.925  9570  9724 I ReactNativeJS: onAuthStateChanged was called with user null // <!-- seeing what we want again, now with patches

So what was happening was:

  • the native code and native SDK had an instance of the listener mapped before the reload,
  • and since react-native 0.74+ changed onCatalystInstanceDestroy to invalidate our native teardown wasn't happening so we weren't removing the mapping
  • after the reload another listener was added but it wasn't the first listener, so no initial state was triggered

With the patches from the PR the old behavior was restored, we are now correctly tearing down the old listener set on a hot-reload, so after the reload when you add a listener it is the first one and you get that initial state update

Additionally, this conforms (again) with the documentation https://rnfirebase.io/auth/usage#listening-to-authentication-state

It is important to remember the onAuthStateChanged listener is asynchronous and will trigger an initial state once a connection with Firebase has been established

...plus it eliminates a platform difference since iOS was still behaving like android was in react-native <= 0.73

Didn't realize how important that initial state was at first, but it really was important between the documentation, the pre-0.74 behavior, and the platform difference!

react-native-firebase 21.5.0 will be out shortly and it should have this fix (along with new feature of firestore sum and avg aggregate queries!)

mikehardy avatar Nov 16 '24 15:11 mikehardy

I was curious so I probed the case of multiple listeners also - the PR fixed them as well

What I observed was that without handling the onCatalystInstanceDestroy deprecation there were no initial state callbacks on listeners added to onAuthStateChanged for the first or any following listeners added until an auth state change was actually triggered somehow. After triggering a post-reload state change they all behaved correctly though and adding new listeners triggered initial state callbacks with no further state changes

With the patches, before or after a hot-reload, any time a listener was added it got an initial state callback.

So should be truly fixed

mikehardy avatar Nov 16 '24 16:11 mikehardy

Thank you so much @mikehardy for taking time out to fix this. Really appreciate your help 🔥.

CodeWithBlaze avatar Nov 16 '24 18:11 CodeWithBlaze

I was having the same issue yesterday, until I find this. For my luck @mikehardy fixed just in time lol. Already updated the package and the issue no longer happens. Thank you so much.

horiondreher avatar Nov 18 '24 01:11 horiondreher

Hey there! I'm able to reproduce this issue once in a while running our expo project on iOS simulator with @react-native-firebase/auth: 21.7.1 and expo-dev-client: 5.0.10. @mikehardy would you recommend uninstalling expo-dev-client as it seems to have issues with this library?

j3lev avatar Mar 31 '25 16:03 j3lev

@j3lev I'm not experienced enough with expo (more correctly: I have no expo experience) that I shouldn't be trusted to give any expo-related advice unfortunately. Your RNFB version is just a hair outdated, but on a scan of the CHANGELOG, there was nothing in the area that should have affected this on our end so I don't think an upgrade here would help

mikehardy avatar Mar 31 '25 17:03 mikehardy

@mikehardy understood and i really appreciate your prompt response. So is this issue related to general RN hot-reload functionality then?

j3lev avatar Mar 31 '25 17:03 j3lev

I just retested this, using my build demonstrator which also demonstrates this functionality (https://github.com/mikehardy/rnfbdemo/blob/main/make-demo.sh -- requires firebase auth emulator to be running on default port on localhost to see it) )

It worked just fine - I see onAuthStateChanged called even after hitting r in the metro console. So I think everything is working as far as the module here is concerned.

I can't speak to expo-dev-client though, as mentioned, apologies

mikehardy avatar Mar 31 '25 18:03 mikehardy