I'm currently working on my first NextJS app after a long hiatus. The first thing I'm working on is a small app that's powered by Firebase.
After reading some documentation on Context and then Firebase's onAuthStateChanged(), I made this component to serve as a way to distribute user login status (or lack thereof) to my entire app:
'use client'
import { onAuthStateChanged } from 'firebase/auth'
import { createContext, useState, useEffect, ReactNode } from 'react'
import { fbAuth } from '../firebase/firebase'
const SessionContext = createContext({ user: {} })
const SessionProvider = ({ children }: { children: ReactNode }) => {
// This should handle current state of who is logged in.
const [currentUser, setUser] = useState({ user: {} })
useEffect(() => {
onAuthStateChanged(fbAuth, (user) => {
console.log('state changed')
if (user) {
setUser({ user })
} else {
setUser({ user: {} })
}
})
})
return <SessionContext value={currentUser}>{children}</SessionContext>
}
export default SessionProvider
This seems like it should work fine, the only issue being that it's a Client Component and requires a "use client" at the top obviously due to use of useState, which is perfectly fine.
The issue comes when I create a small login form in the app that's wrapped with this Context.
I have this example component serving as a basic login form at the moment:
'use client'
import { useActionState } from 'react'
import { barlow } from '../util'
export default function Login() {
const [state, formAction] = useActionState(async (_, formData: FormData) => {
console.log(formData.get('email'))
console.log(formData.get('password'))
}, null)
return (
<div className="card w-3xl rounded-xl border border-neutral-700 bg-base-300 p-4">
<span className={`${barlow.className} text-3xl text-center mb-6`}>Login</span>
<form action={formAction}>
<span className="text-sm text-left mb-1">Login:</span>
<input type="email" autoComplete="email" name="email" className="input mb-4 w-full" />
<span className="text-sm text-left mb-1">Password:</span>
<input type="password" autoComplete="password" name="password" className="input mb-4 w-full" />
<div className="grid grid-cols-2 gap-4">
<button className="btn btn-block btn-primary">Login</button>
<button className="btn btn-block btn-primary">Reset</button>
</div>
</form>
</div>
)
}
However, when I submit the form, it seems that an infinite loop is being triggered and the tab just sort of freezes until I kill it manually and reload the page.
Am I overlooking something in the handler itself? What's causing the infinite re-rendering of stuff? I'm not even logging -in- to anything, just trying to grab the values to get used to the concept of proper form handling using the new APIs.
Thanks in advance! I'm -very- confused and feel like I must be making a simple mistake.