Skip to content

Upgrading to 10.3.0 broke TypeScript detecting getReactNativePersistence function for Expo RN #7584

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

Closed
seanblonien opened this issue Aug 24, 2023 · 35 comments

Comments

@seanblonien
Copy link

seanblonien commented Aug 24, 2023

Operating System

iOS 16.4

Browser Version

Chrome latest

Firebase SDK Version

10.3.0

Firebase SDK Product:

Auth

Describe your project's tooling

Expo tooling React Native app with Firebase JS SDK
(Expo 49.0.0)
(VSCode 1.81.1)

Describe the problem

I was following 10.3.0's new error message:

 WARN  [2023-08-24T04:43:17.235Z]  @firebase/auth: Auth (10.3.0): 
You are initializing Firebase Auth for React Native without providing
AsyncStorage. Auth state will default to memory persistence and will not
persist between sessions. In order to persist auth state, install the package
"@react-native-async-storage/async-storage" and provide it to
initializeAuth:

import { initializeAuth, getReactNativePersistence } from 'firebase/auth';
import ReactNativeAsyncStorage from '@react-native-async-storage/async-storage';
const auth = initializeAuth(app, {
  persistence: getReactNativePersistence(ReactNativeAsyncStorage)
});

introduced by #7570, and yet somehow it was missed that the getReactNativePersistence function is no longer exported from the firebase/auth entry point as of 10.0.0 according to VSCode (does not seem to pick up the native entry point if that function is exported):
image

how do I get my editor to detect the new native entry point?
is this new entry point pattern compatible with managed expo projects, or only bare react-native projects?
(running the numbers quickly, expo is just over 1/3 of the react-native community according to NPM downloads)

#7138 seems to blatantly remove those exported functions without re-exporting them, which seems like they literally are just not exposed and virtually "deleted" from the library. or the native detection just isn't working at all for me, so direction on how to get that working would be helpful

Steps and code to reproduce issue

  1. upgrade firebase to 10.3.0 in Expo 49.0.0 project
  2. try copying the code from above to initialize the auth object
  3. notice the error about it not finding that function
@seanblonien seanblonien added new A new issue that hasn't be categoirzed as question, bug or feature request question labels Aug 24, 2023
@jbalidiong jbalidiong added needs-attention and removed new A new issue that hasn't be categoirzed as question, bug or feature request labels Aug 24, 2023
@steven-kovacs
Copy link

I have been banging my head against the wall for this exact same problem! Anyone have any solutions?

@jbalidiong
Copy link
Contributor

Hi @seanblonien, thanks for bring this to our attention. I was able to replicate the behavior you mentioned. I’ll notify our team about these issues so that they can provide more context and investigate what might be causing this.

@hsubox76
Copy link
Contributor

hsubox76 commented Aug 24, 2023

That's odd, I tested this specifically in a new Expo project (npx create-expo-app) before releasing, specifically, on an iOS simulator. Are you targeting iOS/Android or are you targeting web?

See this comment in a closed issue:
#7425 (comment)

TLDR: getReactNativePersistence hasn't been removed, it seems like you're getting the web bundle, which seems like either a problem with your resolver config (see linked comment above for details), or perhaps you're targeting web?

Here's one way this can happen, if you've customized your Metro config. Link is here: #7115 (comment) and I'll re-paste it for convenience

Just wanted to leave an explanation for anyone else having this issue. This project's metro config added some custom options to resolver but did it by spreading defaultResolver first:

  resolver: {
    ...defaultResolver,
    sourceExts: [...defaultResolver.sourceExts, 'cjs'],
    blacklistRE: exclusionList([/cdk-app\/.*/, /api-app\/.*/]),
  },

Metro's default resolver settings actually look at mainFields ["browser", main"] because Metro is used in non-React Native projects as well and they wanted to keep the defaults more generic. When you create a React Native project with the React Native CLI, the "react-native" field gets add to the beginning of that, but when you put defaultResolver back into the resolver, it overrides that and sets it back to the generic settings. See facebook/metro#807 for an example.

Their solution is just don't spread defaultResolver. Looks like it's not necessary, anything specified in the resolver field will extend defaults I guess, so you don't have to fully fill it out.

Edit: One last thing, if this is the case, you should have been having this problem ever since upgrading from any version of 9 to 10.0.0, that's when the "firebase/auth/react-native" explicit path was removed and replaced with the automatic resolution.

@iM-GeeKy
Copy link

iM-GeeKy commented Aug 24, 2023

@hsubox76 According to the Expo Firebase Docs when upgrading to a version > 9.7.x it looks like they recommend configuring metro. Could that be the cause?

@hsubox76
Copy link
Contributor

So the problem occurs when applying metro config customizations in a way that somehow accidentally sets mainFields back to the default. The example I quoted above does it by spreading defaultResolver. I'm not sure if the example in the Expo docs will do that or not. Is it possible to log or check the value of defaultConfig at the end of that file? See if it includes mainFields, and if it's set to ["browser", "main"] (incorrect) or if it has "react-native" as the first item in the array (correct).

Also if anyone's seeing this error and targeting web with RN (not iOS/Android), let me know.

@iM-GeeKy
Copy link

So the problem occurs when applying metro config customizations in a way that somehow accidentally sets mainFields back to the default. The example I quoted above does it by spreading defaultResolver. I'm not sure if the example in the Expo docs will do that or not. Is it possible to log or check the value of defaultConfig at the end of that file? See if it includes mainFields, and if it's set to ["browser", "main"] (incorrect) or if it has "react-native" as the first item in the array (correct).

Also if anyone's seeing this error and targeting web with RN (not iOS/Android), let me know.

resolverMainFields: [ 'react-native', 'browser', 'main' ],

@hsubox76
Copy link
Contributor

I also just tested out the suggested Metro config in the Expo Firebase docs and it seems to work fine, the resolverMainFields are correct. What error are you seeing? Is it the same as in the original post? ("has no exported member getReactNativePersistence")?

@iM-GeeKy
Copy link

Yeah, thats correct.

Screenshot 2023-08-24 at 1 31 15 PM

@steven-kovacs
Copy link

Same here. I have installed the correct packages but get this.

Screenshot 2023-08-24 133511
Screenshot 2023-08-24 133624

@hsubox76
Copy link
Contributor

hsubox76 commented Aug 24, 2023

Sorry, I didn't realize this was specifically a VSCode editor issue. Am I correct that this isn't affecting any builds?

So I have narrowed down the problem. There's a specific TypeScript definitions file for the React Native auth bundle, and if you look at the package.json for @firebase/auth, it's specified alongside the RN bundle if you use the Node ESM standard exports field for resolution:

"types": "./dist/rn/index.rn.d.ts",

Unfortunately it looks like Metro (by default at least) doesn't use the exports field for module resolution and uses the top level "mainfields". This lets us specify a react-native code bundle here:

"react-native": "dist/rn/index.js",

along with "browser", "main", etc, but unfortunately when using this format, you can't specify a custom typings file to go along with each JS bundle, and (as far as I know) you're stuck with providing one universal type definitions file which is expected to match all the bundles (this is actually rewritten to "auth-public.d.ts" at release time btw):

"typings": "dist/auth.d.ts",

So basically that typings definition bundle will work for the majority of auth bundles (for web, Node), but won't work for RN as it's missing getReactNativePersistence. You can "fix" it temporarily by copying the path from line 22 to line 143 in your project's node_modules/@firebase/auth/package.json. But let me see if there's a way to configure Metro to look at exports or if there's a way to provide multiple typings files using the mainFields resolution scheme.

Edit: Again, let me know if this affects any builds or anything beyond the editor and warnings.

@iM-GeeKy
Copy link

@hsubox76 Yeah, I think that's accurate. Personally speaking, I haven't had any issues running/building with the version of Firebase (10.0.3), but was having to suppress the typescript error in VSCode which I'd prefer to not have to do.

@steven-kovacs
Copy link

I am new so I apologize. Does this mean that Persistence won't work with Expo then? The main reason I ran into this problem was because it doesn't remember that you logged in after you exit the app then return again. That is quite frustrating.

@iM-GeeKy
Copy link

iM-GeeKy commented Aug 24, 2023

I am new so I apologize. Does this mean that Persistence won't work with Expo then? The main reason I ran into this problem was because it doesn't remember that you logged in after you exit the app then return again. That is quite frustrating.

It works. I've followed the code example in the firebase release notes. I've opened a issue/question with the Expo folks as their docs seems to be a little contradictory for firebase 10. From what I read, they make it sound like it's no longer necessary, but then if you remove it you end up with the warning and no persistence.

@hsubox76
Copy link
Contributor

hsubox76 commented Aug 24, 2023

This is just an editor error and I don't think it will affect the actual functionality of the code. The code in the warning should compile and work fine despite what the editor says. (But let me know if it doesn't.)

The first workaround I found so far for the VSCode error is to create a tsconfig.json in your project (if you don't already have one) that just has the contents:

{
  "compilerOptions": {
    "paths": {
      "@firebase/auth": ["./node_modules/@firebase/auth/dist/index.rn.d.ts"]
    }
  },
  "extends": "expo/tsconfig.base"
}

This forces VSCode to look at the index.rn.d.ts typings file for any imports from @firebase/auth. This actually seems to be a TypeScript issue, which is odd, because the default npx create-expo-app doesn't seem on the surface to have any TypeScript in it. But VSCode is using TypeScript to get your syntax highlighting and all that.

There's a very long and controversial issue thread in the TypeScript repo about TypeScript supporting typings from the exports field so I'm guessing that option is probably not going to become available.

Hopefully that helps for now and I will see if it's possible on our end to make auth-public.d.ts even more generic so it covers the RN use case.

@hsubox76
Copy link
Contributor

I am new so I apologize. Does this mean that Persistence won't work with Expo then? The main reason I ran into this problem was because it doesn't remember that you logged in after you exit the app then return again. That is quite frustrating.

It works. I've followed the code example in the firebase release notes. I've opened a issue/question with the Expo folks as their docs seems to be a little contradictory for firebase 10. From what I read, they make it sound like it's no longer necessary, but then if you remove it you end up with the warning and no persistence.

That is on us and not on the Expo folks as we did make persistence "just work" out of the box as of 10.0.0 but had to roll it back as of 10.3.0 as it was negatively impacting non-React-Native users.

@hsubox76 hsubox76 self-assigned this Aug 24, 2023
@seanblonien
Copy link
Author

seanblonien commented Aug 24, 2023

{
  "compilerOptions": {
    "paths": {
      "@firebase/auth": ["./node_modules/@firebase/auth/dist/index.rn.d.ts"]
    }
  },
  "extends": "expo/tsconfig.base"
}

@hsubox76 thank you for this quick fix, error goes away and the expo app bundles successfully without error! 🎉

Conclusion: the code is totally functional as described in the firebase documentation, and this really is just a VSCode/TypeScript issue (exactly what @hsubox76 predicted)

I did have custom metro config, but I did not have to make any additional changes related to the resolver - I just have Expo's suggested resolver code documented here (mentioned previously) -- so do that if you have not already

Lastly, thank you @hsubox76 for seeing if you can update auth-public.d.ts to generically work for RN as well, even though TypeScript should support this out of the box. If you know that issue #, maybe we can tag it here to make them aware that issue is not going away and RN users need that support for TypeScript to work well with editors

@steven-kovacs
Copy link

It seems to be working fine for me now. I didn't realize that the fix that came up in the terminal does actually fix it. I was thrown off by the TypeScript errors. I am new so I have been always making sure the TS is correct, so when I see errors it scares me, haha! All good. I just did what you said and added the path to the tsconfig, and bingo. Thanks all.

@hsubox76
Copy link
Contributor

I'm actually having a hard time pinpointing where the TS problem is. Looking through Typescript issues, it looks like Typescript ought to support the exports field, as long as you set your tsconfig moduleResolution to Node16 or NodeNext and perhaps also set module to that, but that doesn't seem to work for me, perhaps because it only recognizes exports subpaths and standard conditions like require and import and not customConditions like react-native. The TS docs also say they support customConditions: https://www.typescriptlang.org/tsconfig#customConditions but I tried adding "customConditions": ["react-native"] and it doesn't seem to fix it either.

In any case, if there was some kind of typescript config that would support it following the react-native exports path correctly (in a less hacky way than paths), it would still require tinkering around with your tsconfig, as whatever that config might be, it's not built in to Expo's base tsconfig at the moment.

@javashikor
Copy link

I've added the following to my tsconfig.json file to resolve the initial problem:

 {
   "compilerOptions": {
     "paths": {
       "@firebase/auth": ["./node_modules/@firebase/auth/dist/index.rn.d.ts"]
     }
   },
   "extends": "expo/tsconfig.base"
 }

Now I'm getting the following error from Expo Router (V2):

Error loading route "./login.tsx" TypeError: (0 , _auth.getReactNativePersistence) is not a function

@steven-kovacs
Copy link

How are you importing it?

import { initializeAuth, getReactNativePersistence } from "firebase/auth";

And then you also need:

import ReactNativeAsyncStorage from '@react-native-async-storage/async-storage';

I am very new though, so don't take my word for it until someone else gives their input.

@javashikor
Copy link

My mistake. I imported getReactNativePersistence instead of browserSessionPersistence.

@Olalexy1
Copy link

Olalexy1 commented Sep 1, 2023

Thank you so much for this fix.

@mousaormoses
Copy link

1- Navigate to @firebase/auth in node_modules:
Go to your project directory, then navigate to node_modules/@firebase/auth.

2- Edit package.json:
Open the package.json file in a text editor.

3- Modify the typings Field:
Find the line that says:

4- json
Copy code
"typings": "dist/auth.d.ts"
And replace it with:

"typings": "./dist/rn/index.rn.d.ts",
Save and Restart Your Development Server:

@mousaormoses
Copy link

I am having this issue and none of the comments helped :(

try this>

import { initializeApp } from 'firebase/app';
import * as firebaseAuth from 'firebase/auth';
import { initializeAuth } from 'firebase/auth';
import ReactNativeAsyncStorage from '@react-native-async-storage/async-storage';
import firebase from 'firebase/compat/app';
import 'firebase/compat/storage';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
import { getFirestore } from 'firebase/firestore';

export const firebaseConfig = {
YOUR CONFIG
};

export const app = initializeApp(firebaseConfig);
const reactNativePersistence = (firebaseAuth as any).getReactNativePersistence;

export const auth = initializeAuth(app, {
persistence: reactNativePersistence(ReactNativeAsyncStorage)
});

if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}

// Firestore instance
export const db = getFirestore(app);

@google-oss-bot
Copy link
Contributor

Hey @seanblonien. We need more information to resolve this issue but there hasn't been an update in 5 weekdays. I'm marking the issue as stale and if there are no new updates in the next 5 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

@mlev
Copy link

mlev commented Sep 21, 2023

Not sure if there's much more information to give but the issue title is a bit misleading. It's a problem if you use Typescript in a React Native app - not just VSCode. i.e. I see it in IntelliJ but also if I check types with just Typescript cli npx tsc --noEmit.

The provided workaround of specifying the type location in tsconfig works for me but not sure if this is the official solution?

@google-oss-bot
Copy link
Contributor

Hey @seanblonien. We need more information to resolve this issue but there hasn't been an update in 5 weekdays. I'm marking the issue as stale and if there are no new updates in the next 5 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

@seanblonien seanblonien changed the title Upgrading to 10.3.0 broke VSCode detecting getReactNativePersistence function for Expo RN Upgrading to 10.3.0 broke TypeScript detecting getReactNativePersistence function for Expo RN Sep 28, 2023
@google-oss-bot
Copy link
Contributor

Since there haven't been any recent updates here, I am going to close this issue.

@seanblonien if you're still experiencing this problem and want to continue the discussion just leave a comment here and we are happy to re-open this.

@Martijncvv
Copy link

Martijncvv commented Oct 11, 2023

I've added the following to my tsconfig.json file to resolve the initial problem:

 {
   "compilerOptions": {
     "paths": {
       "@firebase/auth": ["./node_modules/@firebase/auth/dist/index.rn.d.ts"]
     }
   },
   "extends": "expo/tsconfig.base"
 }

Now I'm getting the following error from Expo Router (V2):

Error loading route "./login.tsx" TypeError: (0 , _auth.getReactNativePersistence) is not a function

The described solution fixed the getReactNativePersistence for Native, but getting the same error now on web version ((0 , _auth.getReactNativePersistence) is not a function).

Is there a fix if you want the app to work in browser and native?

Currently fixed it like this, not sure if there is a better way?

const persistence = Platform.OS === 'web'
           ? browserSessionPersistence
           : getReactNativePersistence(ReactNativeAsyncStorage);
       const auth = initializeAuth(app, {persistence});

@hsubox76
Copy link
Contributor

See this issue, it may help: #7615 (comment)

I made some suggestions and the user tried a different solution, see if any of those work for you. I think your solution is pretty decent, but as I'm not a RN expert, I don't know if the "official" RN way of splitting it into different files (as linked in that comment) is more robust or anything.

@romaob
Copy link

romaob commented Oct 23, 2023

For me on my Expo React Native app, hsubox76 comment fixed the typescript issue, but then the auth wasn't working on the web version, throwing an error for the getReactNativePersistence:
(0 , _auth.getReactNativePersistence) is not a function
Using Martijncvv comment fixed it so far, now is working as expected on iOS, Android and Web versions.

@jpope19
Copy link

jpope19 commented Oct 28, 2023

I've added the following to my tsconfig.json file to resolve the initial problem:

 {
   "compilerOptions": {
     "paths": {
       "@firebase/auth": ["./node_modules/@firebase/auth/dist/index.rn.d.ts"]
     }
   },
   "extends": "expo/tsconfig.base"
 }

Now I'm getting the following error from Expo Router (V2):

Error loading route "./login.tsx" TypeError: (0 , _auth.getReactNativePersistence) is not a function

The described solution fixed the getReactNativePersistence for Native, but getting the same error now on web version ((0 , _auth.getReactNativePersistence) is not a function).

Is there a fix if you want the app to work in browser and native?

Currently fixed it like this, not sure if there is a better way?

const persistence = Platform.OS === 'web'
           ? browserSessionPersistence
           : getReactNativePersistence(ReactNativeAsyncStorage);
       const auth = initializeAuth(app, {persistence});

what does your tsconfig look like? changing the path to support the rn export breaks the web export. so now it's showing browserSessionPersistence doesn't exist smh

@techgerm
Copy link

@Martijncvv just a quick follow up to see if you can share what your tsconfig looks like with your proposed solution from here: #7584 (comment)

@Martijncvv
Copy link

Martijncvv commented Oct 30, 2023

@Martijncvv just a quick follow up to see if you can share what your tsconfig looks like with your proposed solution from here: #7584 (comment)

Nothing special:

{ "extends": "expo/tsconfig.base", "compilerOptions": { "strict": true } }

I suppress the typescript import error/ warning with a basic @ts-ignore. Hope it will be fixed it soon :)

@techgerm
Copy link

I still faced this issue ((0 , _auth.getReactNativePersistence) is not a function) on native.

When I created a new Expo standalone app, I no longer experienced the issue so it must be related to the fact that the project I'm currently working on is an Expo app inside an Nx monorepo.

This workaround worked for me:

//@ts-ignore
import { getReactNativePersistence } from '@firebase/auth/dist/rn/index.js';

In general though, this issue should not be closed!
It's still a problem and costs a lot of debugging time.

I have a standalone expo with firebase that has a clear repro:
https://github.com/techgerm/expo-app-firebase-bug

@firebase firebase locked and limited conversation to collaborators Nov 5, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests