Fix nextjs console error by not loading from localstorage immedately. Use layout effect instead.

This commit is contained in:
jahooma 2021-12-16 22:09:38 -06:00
parent 96791e11a5
commit 2c9f8e00bf
2 changed files with 24 additions and 25 deletions

View File

@ -1,9 +1,11 @@
import { useEffect, useState } from 'react'
import { getCachedUser, listenForLogin, listenForUser, User } from '../lib/firebase/users'
import { useEffect, useLayoutEffect, useState } from 'react'
import { listenForLogin, listenForUser, User } from '../lib/firebase/users'
export const useUser = () => {
const [user, setUser] = useState<User | null | undefined>(getCachedUser())
useEffect(() => listenForLogin(setUser), [])
const [user, setUser] = useState<User | null | undefined>(undefined)
// Use layout effect to trigger re-render before first paint.
useLayoutEffect(() => listenForLogin(setUser), [])
const userId = user?.id

View File

@ -61,30 +61,34 @@ export function listenForUser(userId: string, setUser: (user: User) => void) {
}
const CACHED_USER_KEY = 'CACHED_USER_KEY'
export function listenForLogin(onUser: (_user: User | null) => void) {
return onAuthStateChanged(auth, async (user) => {
if (user) {
let fetchedUser = await getUser(user.uid)
if (!fetchedUser) {
export function listenForLogin(onUser: (user: User | null) => void) {
const cachedUser = localStorage.getItem(CACHED_USER_KEY)
onUser(cachedUser ? JSON.parse(cachedUser) : null)
return onAuthStateChanged(auth, async (fbUser) => {
if (fbUser) {
let user = await getUser(fbUser.uid)
if (!user) {
// User just created an account; save them to our database.
fetchedUser = {
id: user.uid,
name: user.displayName || 'Default Name',
username: user.displayName?.replace(/\s+/g, '') || 'DefaultUsername',
avatarUrl: user.photoURL || '',
email: user.email || 'default@blah.com',
user = {
id: fbUser.uid,
name: fbUser.displayName || 'Default Name',
username:
fbUser.displayName?.replace(/\s+/g, '') || 'DefaultUsername',
avatarUrl: fbUser.photoURL || '',
email: fbUser.email || 'default@blah.com',
balance: STARTING_BALANCE,
// TODO: use Firestore timestamp?
createdTime: Date.now(),
lastUpdatedTime: Date.now(),
}
await setUser(user.uid, fetchedUser)
await setUser(fbUser.uid, user)
}
onUser(fetchedUser)
onUser(user)
// Persist to local storage, to reduce login blink next time.
// Note: Cap on localStorage size is ~5mb
localStorage.setItem(CACHED_USER_KEY, JSON.stringify(fetchedUser))
localStorage.setItem(CACHED_USER_KEY, JSON.stringify(user))
} else {
// User logged out; reset to null
onUser(null)
@ -93,13 +97,6 @@ export function listenForLogin(onUser: (_user: User | null) => void) {
})
}
export function getCachedUser() {
if (typeof window !== 'undefined') {
const cachedUser = localStorage.getItem(CACHED_USER_KEY)
return cachedUser ? (JSON.parse(cachedUser) as User) : undefined
}
}
export async function firebaseLogin() {
const provider = new GoogleAuthProvider()
signInWithPopup(auth, provider)