Skip to content

Instantly share code, notes, and snippets.

@jeffreymeng
Last active September 4, 2023 15:27
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeffreymeng/78bd7f6b0f301fa5ef04359cd512222b to your computer and use it in GitHub Desktop.
Save jeffreymeng/78bd7f6b0f301fa5ef04359cd512222b to your computer and use it in GitHub Desktop.
Gatsby React Firebase Authentication Hook

As opposed to useAuthState in react-firebase-hooks (which doesn't work with gatsby builds), this is designed to work with gatsby-plugin-firebase.

Requires React and firebase

Usage example:

import firebase from "gatsby-plugin-firebase"
import useAuthState from ...

function MyComponent() {
const [user, loading, error] = useAuthState(firebase); // NOT firebase.auth()

// ...
if (loading) return <p>Loading...</p>
if (user) return <p>Hi, {user.displayName}!</p>
if (error) //handle error

}
/* by Jeffrey Meng | MIT License */
import {useEffect, useReducer, useState} from "react";
export default function useAuthState(firebase) {
const [auth, setAuth] = useState(undefined);
const [state, dispatch] = useReducer(
(state, action) => {
switch (action.type) {
case "auth_state_changed":
return {
...state,
user: action.user,
loading: false,
};
case "error":
return {
...state,
error: action.error,
loading: false,
};
}
},
{
user: undefined,
loading: true,
error: undefined,
}
);
useEffect(() => {
setAuth(firebase.auth());
}, [firebase]);
useEffect(() => {
if (auth === undefined) return;
const unsubscribe = auth.onAuthStateChanged(
user => {
dispatch({type: "auth_state_changed", user});
},
error => {
dispatch({type: "error", error});
}
);
return () => {
unsubscribe();
};
}, [auth]);
return [state.user, state.loading, state.error];
}
/* by Jeffrey Meng | MIT License */
import {useEffect, useReducer, useState} from "react";
import {auth, User} from "firebase";
interface FirebaseWithAuth {
auth: () => auth.Auth;
}
export default function useAuthState(
firebase: FirebaseWithAuth
): [User | undefined, boolean, auth.Error | undefined] {
const [auth, setAuth] = useState<undefined | auth.Auth>(undefined);
interface State {
user: User | undefined;
loading: boolean;
error: auth.Error | undefined;
}
type Action =
| { type: "auth_state_changed"; user: User }
| { type: "error"; error: auth.Error };
const [state, dispatch] = useReducer(
(state: State, action: Action) => {
switch (action.type) {
case "auth_state_changed":
return {
...state,
user: action.user,
loading: false,
};
case "error":
return {
...state,
error: action.error,
loading: false,
};
}
},
{
user: undefined,
loading: true,
error: undefined,
}
);
useEffect(() => {
setAuth(firebase.auth());
}, [firebase]);
useEffect(() => {
if (auth === undefined) return;
const unsubscribe = auth.onAuthStateChanged(
(user): void => {
dispatch({type: "auth_state_changed", user});
},
(error: auth.Error): void => {
dispatch({type: "error", error});
}
);
return (): void => {
unsubscribe();
};
}, [auth]);
return [state.user, state.loading, state.error];
}
@zidkim
Copy link

zidkim commented Sep 26, 2021

Hmm, breaks for me during build.

WebpackError: TypeError: _lib_firebase_useAuthState__WEBPACK_IMPORTED_MODULE_5 ___default(...) is not a function

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