How to update client component after server action was triggered?

I was able to fix it by creating a context around the app for the user.
And then changing the login server action to return the user:

export async function login(formData: FormData) {
  const supabase = await createClient()
  const data = {
    email: formData.get('email') as string,
    password: formData.get('password') as string,
  }
  const { data: authData, error } = await supabase.auth.signInWithPassword(data)
  if (error) {
    throw new Error(error.message)
  }
  revalidatePath('/')
  return authData.session?.user || null
}

And then on the login page which is client side, update the user:

"use client"
import { login } from "./actions"
import { useRouter } from "next/navigation"
import { useUser } from "@/context/UserContext"

export default function LoginPage() {
  const router = useRouter()
  const { setUser } = useUser()

  async function handleSubmit(formData: FormData) {
    const loggedInUser = await login(formData) // Modify login to return user
    if (loggedInUser) {
      setUser(loggedInUser)
      router.refresh()      // Force the header to re-check session
      router.push("/private")
    } else {
      // Handle login error if needed
    }
  }

  return (
    <form onSubmit={async (e) => {
      e.preventDefault()
      await handleSubmit(new FormData(e.currentTarget))
    }}>
      <label htmlFor="email">Email:</label>
      <input id="email" name="email" type="email" required />
      <label htmlFor="password">Password:</label>
      <input id="password" name="password" type="password" required />
      <button type="submit">Log in</button>
    </form>
  )
}
2 Likes