firebaseui-web-react icon indicating copy to clipboard operation
firebaseui-web-react copied to clipboard

Upgraded to React 18, updated dependencies, fixed "AuthUI instance is deleted" error

Open gvillenave opened this issue 2 years ago • 42 comments

  • Updated peer dependency to support React 18
  • Updated all dependencies (Babel, Webpack, ...)
  • Replaced React class component with function component
  • Updated component lifecycle management from componentWillMount/componentWillUnmount to a useEffect hook
  • Fixed #172
  • Switched from using a hardcoded element ID to a React ref with useRef
  • Updated example app accordingly
  • Switched example app from using extract-text-webpack-plugin (now deprecated) to mini-css-extract-plugin and postcss
  • Updated README
  • Bumped package version to 7.0.0

gvillenave avatar May 11 '22 00:05 gvillenave

Hi, is it ready to be merged?

chuhancheng avatar May 18 '22 06:05 chuhancheng

When is it getting merged?

modsushi avatar May 18 '22 07:05 modsushi

@jhuleatt can you review and merge?

gvillenave avatar May 18 '22 07:05 gvillenave

Hi all. I need this PR merged right now. Thank you

cuongnvn avatar May 24 '22 03:05 cuongnvn

Hey when is this fix getting merged?

aamancio avatar May 26 '22 18:05 aamancio

@jhuleatt any feedback on the PR? Can we get this merged soon?

gvillenave avatar Jun 01 '22 17:06 gvillenave

waiting for merge

zettry1 avatar Jun 01 '22 19:06 zettry1

waiting for merge +1

paviln avatar Jun 03 '22 19:06 paviln

waiting for merge +2

MaurizioTonelli avatar Jun 03 '22 20:06 MaurizioTonelli

I too would greatly appreciate this getting merged

YGKtech avatar Jun 08 '22 21:06 YGKtech

React solution

Based on this PR, if anyone is using React (create-react-app and not Next.js or other) and is looking for a way of solving this issue, you can get rid of firebaseui-web-react and just use firebaseui. These are the steps to do that:

  • Remove react-firebaseui (yarn remove react-firebaseui)
  • Add firebaseui (yarn add firebaseui)
  • Copy the below code as StyledFirebaseAuth.tsx
import { useEffect, useRef, useState } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import * as firebaseui from 'firebaseui';
import 'firebaseui/dist/firebaseui.css';

interface Props {
    // The Firebase UI Web UI Config object.
    // See: https://github.com/firebase/firebaseui-web#configuration
    uiConfig: firebaseui.auth.Config;
    // Callback that will be passed the FirebaseUi instance before it is
    // started. This allows access to certain configuration options such as
    // disableAutoSignIn().
    uiCallback?(ui: firebaseui.auth.AuthUI): void;
    // The Firebase App auth instance to use.
    firebaseAuth: any; // As firebaseui-web
    className?: string;
}


const StyledFirebaseAuth = ({uiConfig, firebaseAuth, className, uiCallback}: Props) => {
    const [userSignedIn, setUserSignedIn] = useState(false);
    const elementRef = useRef(null);

    useEffect(() => {
        // Get or Create a firebaseUI instance.
        const firebaseUiWidget = firebaseui.auth.AuthUI.getInstance() || new firebaseui.auth.AuthUI(firebaseAuth);
        if (uiConfig.signInFlow === 'popup')
            firebaseUiWidget.reset();

        // We track the auth state to reset firebaseUi if the user signs out.
        const unregisterAuthObserver = onAuthStateChanged(firebaseAuth, (user) => {
            if (!user && userSignedIn)
                firebaseUiWidget.reset();
            setUserSignedIn(!!user);
        });

        // Trigger the callback if any was set.
        if (uiCallback)
            uiCallback(firebaseUiWidget);

        // Render the firebaseUi Widget.
        // @ts-ignore
        firebaseUiWidget.start(elementRef.current, uiConfig);

        return () => {
            unregisterAuthObserver();
            firebaseUiWidget.reset();
        };
    }, [firebaseui, uiConfig]);

    return <div className={className} ref={elementRef} />;
};

export default StyledFirebaseAuth;

That's it! You can use this component without the need for this library. If you need FirebaseAuth instead of the StyledFirebaseAuth, you can just remove the import 'firebaseui/dist/firebaseui.css'; line from the component and you'll be good to go!

I just did this for my personal project and reduced the main bundle size by ~9KB.

MartinXPN avatar Jun 09 '22 19:06 MartinXPN

waiting for merge +3

Skyblueballykid avatar Jun 10 '22 18:06 Skyblueballykid

me too!

lewis-cobry avatar Jun 14 '22 15:06 lewis-cobry

Please merge it :)

frontcodelover avatar Jun 14 '22 18:06 frontcodelover

merge 🙏

th-m avatar Jun 23 '22 21:06 th-m

Pretty please with chocolate sprinkles on top? 🙏

IAmKio avatar Jun 25 '22 07:06 IAmKio

Give me permission and I'll merge it. This project feels unmaintained.

Skyblueballykid avatar Jul 06 '22 04:07 Skyblueballykid

waiting for merge +999

xhonorate avatar Jul 13 '22 19:07 xhonorate

@jhuleatt

Can this be merged?

gbourne1 avatar Jul 14 '22 16:07 gbourne1

Please merge this; no reason not to.

wiktor-cobry avatar Jul 18 '22 10:07 wiktor-cobry

Let's go! @jhuleatt Would be really nice if you would find the time, thanks!

juliankleine avatar Jul 18 '22 18:07 juliankleine

@jhuleatt If you can't find the time is it possible to dispatch the review to a different maintainer of this project? I think a lot of people would love to see this PR being merged. Thanks for your time!

juliankleine avatar Aug 03 '22 17:08 juliankleine

Has anyone found a way of solving this using Next.js?

fsalcedo55 avatar Aug 06 '22 17:08 fsalcedo55

Please merge 🙏

rubencarv avatar Aug 08 '22 12:08 rubencarv

@jhuleatt and @Skyblueballykid , this merge is important for my team's project! Please be a kind soul and help us unblock. At least, by when should this PR get merged in?

karkir0003 avatar Aug 08 '22 20:08 karkir0003

Next.js solution

For anyone looking for a solution for Next.js, you can use the following code and completely get rid of this library:

  • Remove react-firebaseui (yarn remove react-firebaseui)
  • Add firebaseui (yarn add firebaseui)
  • Copy the below code as StyledFirebaseAuth.tsx
import { useEffect, useRef, useState } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import 'firebaseui/dist/firebaseui.css';
import {auth} from "firebaseui";

interface Props {
    // The Firebase UI Web UI Config object.
    // See: https://github.com/firebase/firebaseui-web#configuration
    uiConfig: auth.Config;
    // Callback that will be passed the FirebaseUi instance before it is
    // started. This allows access to certain configuration options such as
    // disableAutoSignIn().
    uiCallback?(ui: auth.AuthUI): void;
    // The Firebase App auth instance to use.
    firebaseAuth: any; // As firebaseui-web
    className?: string;
}


const StyledFirebaseAuth = ({uiConfig, firebaseAuth, className, uiCallback}: Props) => {
    const [firebaseui, setFirebaseui] = useState<typeof import('firebaseui') | null>(null);
    const [userSignedIn, setUserSignedIn] = useState(false);
    const elementRef = useRef(null);

    useEffect(() => {
        // Firebase UI only works on the Client. So we're loading the package only after
        // the component has mounted, so that this works when doing server-side rendering.
        setFirebaseui(require('firebaseui'));
    }, []);


    useEffect(() => {
        if (firebaseui === null )
            return;

        // Get or Create a firebaseUI instance.
        const firebaseUiWidget = firebaseui.auth.AuthUI.getInstance() || new firebaseui.auth.AuthUI(firebaseAuth);
        if (uiConfig.signInFlow === 'popup')
            firebaseUiWidget.reset();

        // We track the auth state to reset firebaseUi if the user signs out.
        const unregisterAuthObserver = onAuthStateChanged(firebaseAuth, user => {
            if (!user && userSignedIn)
                firebaseUiWidget.reset();
            setUserSignedIn(!!user);
        });

        // Trigger the callback if any was set.
        if (uiCallback)
            uiCallback(firebaseUiWidget);

        // Render the firebaseUi Widget.
        // @ts-ignore
        firebaseUiWidget.start(elementRef.current, uiConfig);

        return () => {
            unregisterAuthObserver();
            firebaseUiWidget.reset();
        };
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [firebaseui, uiConfig]);

    return <div className={className} ref={elementRef} />;
};

export default StyledFirebaseAuth;

That's it! You can use this component without the need for this library. If you need FirebaseAuth instead of the StyledFirebaseAuth, you can just remove the import 'firebaseui/dist/firebaseui.css'; line from the component and you'll be good to go!

MartinXPN avatar Aug 15 '22 19:08 MartinXPN

Waiting for merge 🙏

LeandroLeon avatar Aug 18 '22 06:08 LeandroLeon

pls merge!

michaelangeloio avatar Aug 19 '22 21:08 michaelangeloio

React solution

Based on this PR, if anyone is using React (create-react-app and not Next.js or other) and is looking for a way of solving this issue, you can get rid of firebaseui-web-react and just use firebaseui. These are the steps to do that:

  • Remove react-firebaseui (yarn remove react-firebaseui)
  • Add firebaseui (yarn add firebaseui)
  • Copy the below code as StyledFirebaseAuth.tsx
import { useEffect, useRef, useState } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import * as firebaseui from 'firebaseui';
import 'firebaseui/dist/firebaseui.css';

interface Props {
    // The Firebase UI Web UI Config object.
    // See: https://github.com/firebase/firebaseui-web#configuration
    uiConfig: firebaseui.auth.Config;
    // Callback that will be passed the FirebaseUi instance before it is
    // started. This allows access to certain configuration options such as
    // disableAutoSignIn().
    uiCallback?(ui: firebaseui.auth.AuthUI): void;
    // The Firebase App auth instance to use.
    firebaseAuth: any; // As firebaseui-web
    className?: string;
}


const StyledFirebaseAuth = ({uiConfig, firebaseAuth, className, uiCallback}: Props) => {
    const [userSignedIn, setUserSignedIn] = useState(false);
    const elementRef = useRef(null);

    useEffect(() => {
        // Get or Create a firebaseUI instance.
        const firebaseUiWidget = firebaseui.auth.AuthUI.getInstance() || new firebaseui.auth.AuthUI(firebaseAuth);
        if (uiConfig.signInFlow === 'popup')
            firebaseUiWidget.reset();

        // We track the auth state to reset firebaseUi if the user signs out.
        const unregisterAuthObserver = onAuthStateChanged(firebaseAuth, (user) => {
            if (!user && userSignedIn)
                firebaseUiWidget.reset();
            setUserSignedIn(!!user);
        });

        // Trigger the callback if any was set.
        if (uiCallback)
            uiCallback(firebaseUiWidget);

        // Render the firebaseUi Widget.
        // @ts-ignore
        firebaseUiWidget.start(elementRef.current, uiConfig);

        return () => {
            unregisterAuthObserver();
            firebaseUiWidget.reset();
        };
    }, [firebaseui, uiConfig]);

    return <div className={className} ref={elementRef} />;
};

export default StyledFirebaseAuth;

That's it! You can use this component without the need for this library. If you need FirebaseAuth instead of the StyledFirebaseAuth, you can just remove the import 'firebaseui/dist/firebaseui.css'; line from the component and you'll be good to go!

I just did this for my personal project and reduced the main bundle size by ~9KB.

Perfect and worked like a charm! Thanks.

gbourne1 avatar Aug 23 '22 17:08 gbourne1

Hey guys come on! Many people are looking for this, it is as simple as merging it, just do it or give access to someone else that will actually maintain it.

Sp3ctreZero avatar Sep 07 '22 01:09 Sp3ctreZero