Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[🐛] Android - onAuthStateChanged does not fire when I refresh the app from the metro terminal by pressing R #7819

Closed
mehtaanirudh opened this issue Jun 1, 2024 · 23 comments · Fixed by #8139
Labels
plugin: authentication Firebase Authentication resolution: fixed A fix has been merged into main. type: bug New bug report

Comments

@mehtaanirudh
Copy link

mehtaanirudh commented Jun 1, 2024

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 mehtaanirudh added help: needs-triage Issue needs additional investigation/triaging. type: bug New bug report labels Jun 1, 2024
Copy link

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 github-actions bot added the Type: Stale Issue has become stale - automatically added by Stale bot label Jun 29, 2024
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Jul 15, 2024
@wneild
Copy link

wneild commented Jul 16, 2024

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"

@vm02
Copy link

vm02 commented Aug 19, 2024

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"

@enlob
Copy link

enlob commented Aug 23, 2024

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",

@NicolasMarcinkowski
Copy link

NicolasMarcinkowski commented Sep 16, 2024

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",

@devpascoe
Copy link

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

@RANGELJ
Copy link

RANGELJ commented Oct 4, 2024

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

@horacio-a
Copy link

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",

@CodeWithBlaze
Copy link

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 ?

@mikehardy
Copy link
Collaborator

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

And then after do you see any of these re-registering?

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 mikehardy reopened this Nov 15, 2024
@CodeWithBlaze
Copy link

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 },[])

@mikehardy
Copy link
Collaborator

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
Copy link
Collaborator

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 ?

@CodeWithBlaze
Copy link

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

@mikehardy
Copy link
Collaborator

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

@CodeWithBlaze
Copy link

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

@mikehardy
Copy link
Collaborator

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?

@CodeWithBlaze
Copy link

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 ?

@MicroDroid
Copy link

MicroDroid commented Nov 16, 2024 via email

@mikehardy mikehardy changed the title [🐛] Androind - onAuthStateChanged does not fire when I refresh the app from the metro teminal by pressing R [🐛] Android - onAuthStateChanged does not fire when I refresh the app from the metro teminal by pressing R Nov 16, 2024
@mikehardy mikehardy changed the title [🐛] Android - onAuthStateChanged does not fire when I refresh the app from the metro teminal by pressing R [🐛] Android - onAuthStateChanged does not fire when I refresh the app from the metro terminal by pressing R Nov 16, 2024
@mikehardy
Copy link
Collaborator

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
Copy link
Collaborator

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 mikehardy added plugin: authentication Firebase Authentication resolution: fixed A fix has been merged into main. and removed help: needs-triage Issue needs additional investigation/triaging. Type: Stale Issue has become stale - automatically added by Stale bot labels Nov 16, 2024
@CodeWithBlaze
Copy link

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

@horiondreher
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plugin: authentication Firebase Authentication resolution: fixed A fix has been merged into main. type: bug New bug report
Projects
None yet
Development

Successfully merging a pull request may close this issue.