Skip to content

Instantly share code, notes, and snippets.

@omochi
Created May 10, 2023 02:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save omochi/7e0963918e191d5e8023b9b9ce8e527f to your computer and use it in GitHub Desktop.
Save omochi/7e0963918e191d5e8023b9b9ce8e527f to your computer and use it in GitHub Desktop.
import { Auth } from "@firebase/auth";
import * as firebaseui from "firebaseui";
import { ReactElement, useEffect, useRef, useState } from "react";
import { Random } from "../../components/Random";
import { Box, BoxProps } from "@chakra-ui/react";
export type FirebaseAuthViewProps = {
auth: Auth;
config: firebaseui.auth.Config;
} & BoxProps;
class FirebaseAuthViewImpl {
/*
UIの削除が非同期なので、
マウントされている、かつ、削除中ではない時に、開始する。
削除はアンマウントから起動するが、
既に削除中であれば何もしない。
*/
auth: Auth;
ui: firebaseui.auth.AuthUI | null;
config: firebaseui.auth.Config;
elementID: string;
// マウントされている
isMounted: boolean;
// startを呼び出して、deleteを呼び出す前
isStarted: boolean;
// delete呼び出して実行中
deleteTask: Promise<void> | null;
constructor(auth: Auth, config: firebaseui.auth.Config, elementID: string) {
this.auth = auth;
this.ui = null;
this.config = config;
this.elementID = elementID;
this.isMounted = true;
this.isStarted = false;
this.deleteTask = null;
}
private start() {
if (this.ui == null) {
this.ui = new firebaseui.auth.AuthUI(this.auth);
}
this.ui!.start("#" + this.elementID, this.config);
this.isStarted = true;
}
private delete() {
this.isStarted = false;
this.deleteTask = this.ui!.delete().then(() => {
this.deleteTask = null;
this.ui = null;
this.mayStart();
});
}
private mayStart() {
if (this.isMounted && this.deleteTask == null) {
this.start();
}
}
onMount() {
this.isMounted = true;
this.mayStart();
}
onUnmount() {
if (this.isStarted && this.deleteTask == null) {
this.delete();
}
this.isMounted = false;
}
}
export function FirebaseAuthView(props: FirebaseAuthViewProps): ReactElement {
const {
auth,
config,
...rest
} = props;
const [id, setID] = useState<string>(() => `auth-${ Random.htmlID() }`);
const implRef = useRef<FirebaseAuthViewImpl | null>(null);
useEffect(() => {
if (implRef.current == null) {
implRef.current = new FirebaseAuthViewImpl(auth, config, id);
}
implRef.current!.onMount();
return () => {
implRef.current!.onUnmount();
}
}, []);
return <Box id={ id } {...rest}></Box>
}
@omochi
Copy link
Author

omochi commented May 10, 2023

公式のやつが高速なmount/unmountで正しく動かないため、React.StrictMode で利用できなかったので、自作した。
結局不要になったのでgistに供養する。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment