Skip to content

Instantly share code, notes, and snippets.

@yarabramasta
Last active August 21, 2022 14:05
Show Gist options
  • Save yarabramasta/8ecec7e2ef2b9a51a53edb8e21e6e88a to your computer and use it in GitHub Desktop.
Save yarabramasta/8ecec7e2ef2b9a51a53edb8e21e6e88a to your computer and use it in GitHub Desktop.
Firebase Auth x Next JS

Firebase App Configuration

Import this on top of application entry, such as pages/_app.tsx

NOTE: Make sure to import without resolving it import '../lib/firebase'

// firebase.ts

// import { getAnalytics } from 'firebase/analytics';
import { getApp, getApps, initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
// import { getPerformance } from 'firebase/performance';

const firebaseAppConfig = {
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
  storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
  measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID
};

const isServer: boolean = typeof window === 'undefined';

if (!getApps().length) {
  const _app = initializeApp(firebaseAppConfig);
  if (isServer === false) {
    if ('measurementId' in firebaseAppConfig) {
      // getAnalytics(_app);
      // getPerformance(_app);
    }
  }
}

const app = getApp();
export const auth = getAuth(app);

export default app;

Auth State

Manage firebase auth state change.

Keep track of firebase user using react context provider state management.

Also contain some of firebase auth functions.

NOTE: You can extend the functions by adding new property at IAuthContext.

// AuthProviser.tsx

// import {...} from 'firebase/auth';
import { auth } from '../lib/firebase';

interface IAuthContext {
  user: User | null;
  error: Error | null;
  loading: boolean;
  signInWithEmail(email: string, password: string): void;
  signInWithGoogle(): void;
  signUp(email: string, password: string): void;
  signOut(): void;
}

export const AuthContext = createContext<IAuthContext>({
  user: null,
  error: null,
  loading: true,
  signInWithEmail(email: string, password: string) {},
  signInWithGoogle() {},
  signUp(email: string, password: string) {},
  signOut() {}
});

const AuthProvider: React.ReactWithChildren = ({ children }) => {
  const [user, setUser] = useState<User | null>(null);
  const [error, setError] = useState<Error | null>(null);
  const [loading, setLoading] = useState<boolean>(true);

  useEffect(() => {
    setLoading(true);
    const unsub = onAuthStateChanged(auth, user => {
      setUser(user);
      setError(null);
      setLoading(false);
    });
    return unsub;
  }, []);

  const _signInWithEmail = (email: string, password: string) => {
    setLoading(true);
    signInWithEmailAndPassword(auth, email, password)
      .catch(setError)
      .finally(() => setLoading(false));
  };

  const _signInWithGoogle = () => {
    setLoading(true);
    signInWithPopup(auth, new GoogleAuthProvider())
      .catch(setError)
      .finally(() => setLoading(false));
  };

  const _signUp = (email: string, password: string) => {
    setLoading(true);
    createUserWithEmailAndPassword(auth, email, password)
      .catch(setError)
      .finally(() => setLoading(false));
  };

  const _signOut = () => {
    setLoading(true);
    signOut(auth)
      .catch(setError)
      .finally(() => setLoading(false));
  };

  const value = {
    user,
    error,
    loading,
    signInWithEmail: _signInWithEmail,
    signInWithGoogle: _signInWithGoogle,
    signUp: _signUp,
    signOut: _signOut
  };

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};

export default AuthProvider;

Usage

// Context Usage

/** @ref AuthProvider value */
const { user } = useContext(AuthContext);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment