Factor out FirebaseAppContext.

pull/216/head
Atul Varma 2021-08-22 08:42:23 -04:00
rodzic bec2c4eb49
commit 3fc6a699a0
2 zmienionych plików z 39 dodań i 17 usunięć

Wyświetl plik

@ -8,7 +8,7 @@ import {
Auth, Auth,
User, User,
} from "firebase/auth"; } from "firebase/auth";
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useContext, useEffect, useState } from "react";
const DEFAULT_APP_CONFIG: FirebaseOptions = { const DEFAULT_APP_CONFIG: FirebaseOptions = {
apiKey: "AIzaSyAV1kkVvSKEicEa8rLke9o_BxYBu1rb8kw", apiKey: "AIzaSyAV1kkVvSKEicEa8rLke9o_BxYBu1rb8kw",
@ -51,20 +51,40 @@ export interface AuthContext {
} }
type FirebaseGithubAuthState = { type FirebaseGithubAuthState = {
app: FirebaseApp;
auth: Auth; auth: Auth;
provider: GithubAuthProvider; provider: GithubAuthProvider;
}; };
export const FirebaseAppContext = React.createContext<FirebaseApp | null>(null);
/** /**
* A Firebase GitHub authentication provider. * A Firebase app provider. Any other components that use Firebase must
* be a child of this.
* *
* Note this component is assumed to never be unmounted, nor * Note this component is assumed to never be unmounted, nor
* for its props to change. * for its non-children props to change.
*/ */
export const FirebaseGithubAuthProvider: React.FC<{ export const FirebaseAppProvider: React.FC<{ config?: FirebaseOptions }> = ({
config?: FirebaseOptions; config,
}> = ({ config, children }) => { children,
}) => {
const [app, setApp] = useState<FirebaseApp | null>(null);
useEffect(() => {
setApp(initializeApp(config || DEFAULT_APP_CONFIG));
}, [config]);
return <FirebaseAppContext.Provider value={app} children={children} />;
};
/**
* A Firebase GitHub authentication provider. Must be a child of a
* `FirebaseAppProvider`.
*
* Note this component is assumed to never be unmounted.
*/
export const FirebaseGithubAuthProvider: React.FC<{}> = ({ children }) => {
const app = useContext(FirebaseAppContext);
const [state, setState] = useState<FirebaseGithubAuthState | null>(null); const [state, setState] = useState<FirebaseGithubAuthState | null>(null);
const [user, setUser] = useState<User | null>(null); const [user, setUser] = useState<User | null>(null);
const [error, setError] = useState<string | undefined>(undefined); const [error, setError] = useState<string | undefined>(undefined);
@ -72,17 +92,17 @@ export const FirebaseGithubAuthProvider: React.FC<{
const handleError = (e: Error) => setError(e.message); const handleError = (e: Error) => setError(e.message);
useEffect(() => { useEffect(() => {
const app = initializeApp(config || DEFAULT_APP_CONFIG); if (!app) return;
const auth = getAuth(app); const auth = getAuth(app);
const provider = new GithubAuthProvider(); const provider = new GithubAuthProvider();
setState({ app, auth, provider }); setState({ auth, provider });
onAuthStateChanged(auth, setUser); onAuthStateChanged(auth, setUser);
}, [config]); }, [app]);
const context: AuthContext = { const context: AuthContext = {
loggedInUser: user && user.displayName, loggedInUser: user && user.displayName,
providerName: "GitHub", providerName: state && "GitHub",
error, error,
login: useCallback(() => { login: useCallback(() => {
setError(undefined); setError(undefined);

Wyświetl plik

@ -1,6 +1,6 @@
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import { FirebaseGithubAuthProvider } from "./auth"; import { FirebaseAppProvider, FirebaseGithubAuthProvider } from "./auth";
import { PageContext, PAGE_QUERY_ARG } from "./page"; import { PageContext, PAGE_QUERY_ARG } from "./page";
import { pageNames, Pages, toPageName, DEFAULT_PAGE } from "./pages"; import { pageNames, Pages, toPageName, DEFAULT_PAGE } from "./pages";
@ -57,11 +57,13 @@ const App: React.FC<{}> = (props) => {
}; };
return ( return (
<FirebaseAppProvider>
<FirebaseGithubAuthProvider> <FirebaseGithubAuthProvider>
<PageContext.Provider value={ctx}> <PageContext.Provider value={ctx}>
<PageComponent /> <PageComponent />
</PageContext.Provider> </PageContext.Provider>
</FirebaseGithubAuthProvider> </FirebaseGithubAuthProvider>
</FirebaseAppProvider>
); );
}; };