#Conform v1 fails to print login error on 1st attempt. Prints it fine on 2nd or later attempts.

1 messages · Page 1 of 1 (latest)

rapid storm
#

I have a simple Login form with Remix + Conform v1 -> https://github.com/deadcoder0904/conform-remix-login

It works but for 1st failure attempt, it gives error.

export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData()
  const submission = await parseWithZod(formData, {
    schema: LoginFormSchema.transform(async (data, ctx) => {
      const session = await login(data)
      console.log({ session })
      if (!session) {
        ctx.addIssue({
          path: ['email'],
          code: z.ZodIssueCode.custom,
          message: 'Invalid email or password',
        })
        return z.NEVER
      }
      return { ...data, session }
    }),
    async: true,
  })

  console.log({ submission })
  console.log(submission.status !== 'success')
  if (submission.status !== 'success' || !submission.value?.session) {
    console.log('inside')
    return json(
      { result: submission.reply({ hideFields: ['password'] }) },
      { status: submission.status === 'error' ? 400 : 200 }
    )
  }
  console.log('hi')
  const { session } = submission.value
  if (!session) {
    return json(
      { status: 'error', result: submission.reply() },
      { status: 400 }
    )
  }

  return redirect('/dashboard', {
    headers: {
      'Set-Cookie': 'LoggedIn',
    },
  })
}

It used to work before v1 upgrade but somehow fails now. Idk if the issue is my code or Conform v1 itself isnt working well with Remix.

I followed kent's epic-stack code -> https://github.com/epicweb-dev/epic-stack/blob/main/app/routes/_auth%2B/login.tsx

Full issue which has the above code expanded as Discord has limits -> https://github.com/edmundhung/conform/discussions/527

#

Conform v1 fails to print login error on 1st attempt. Prints it fine on 2nd or later attempts.

bold spruce
#

why are you validating the login within a schema at the first place
you can try catch the login and return a form or field error

      status: 201,
    })
  } catch (error) {
    console.error(error)
    if (error instanceof BadRequestError) {
      return json(
        submission.reply({
          formErrors: [error.message],
        }),

        {
          status: 400,
        }
      )
    }
    throw error
  }```
#

full example

  const { accessToken } = await isAuthenticated(request, request.headers)
  const formData = await request.formData()
  const intent = formData.get('intent') as 'create' | 'update' | 'delete'
  const submission = parseWithZod(formData, {
    schema: intent === 'delete' ? z.any() : gameInputSchema,
  })
  if (submission.status !== 'success') {
    return json(submission.reply(), {
      status: submission.status === 'error' ? 400 : 200,
    })
  }
  try {
    const gameId = String(formData.get('id'))

    switch (intent) {
      case 'create':
        await createGame(accessToken, submission.value)
        break
      case 'update':
        await updateGame(accessToken, gameId, submission.value)
        break
      case 'delete':
        await deleteGame(accessToken, gameId)
        break
      default:
        throw new Error('Invalid intent')
    }
    return json(submission.reply(), {
      status: 201,
    })
  } catch (error) {
    console.error(error)
    if (error instanceof BadRequestError || error instanceof NotFoundError) {
      return json(
        submission.reply({
          formErrors: [error.message],
        }),

        {
          status: 400,
        }
      )
    }
    throw error
  }
}
rapid storm
#

i just copied it from epic-stack by kentcdodds. he does the same. thank you tho i'll try it.

bold spruce
#

mmm ,I dont know what is the use case for him to do it this way ,
I just do try catch , figured it out myself

rapid storm
#

where do BadRequestError & NotFoundError come from?

#

i did update my code. still gotta test it:

export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData()
  const submission = await parseWithZod(formData, {
    schema: LoginFormSchema,
    async: true
  })

  console.log(JSON.stringify(submission, null, 2))
  console.log(submission.status !== 'success')
  if (submission.status !== 'success') {
    console.log('inside')
    return json(
      { result: submission.reply({ hideFields: ['password'] }) },
      { status: submission.status === 'error' ? 400 : 200 }
    )
  }

  try {
   const session = await login(submission.value)
    console.log('hi')
    if (!session) {
      return json(
        { status: 'error', result: submission.reply() },
        { status: 400 }
      )
    }
  
    const toastSession = await getToastSession(request)
    toastSession.flash(SESSION_MESSAGE, `Login successful!!!`)
  
    const headers = new Headers()
    headers.append('Set-Cookie', await commitToastSession(toastSession))
  
    return redirect('/dashboard', { headers })
  } catch(err) {
    if (err instanceof BadRequestError || err instanceof NotFoundError) {
      return json(
        submission.reply({
          formErrors: [err.message],
        }),

        {
          status: 400,
        }
      )
    }
    throw err
  }
}
bold spruce
#

those are custom errors from me , replace them by throwing a known error in the login function that you can catch

rapid storm
# bold spruce those are custom errors from me , replace them by throwing a known error in the ...

so i tried it today. now, it doesnt even show error even after 2nd time.

export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData()
  const submission = await parseWithZod(formData, {
    schema: LoginFormSchema,
    async: true,
  })

  console.log(JSON.stringify(submission, null, 2))
  console.log(submission.status !== 'success')
  if (submission.status !== 'success') {
    console.log('inside')
    return json(
      { result: submission.reply({ hideFields: ['password'] }) },
      { status: submission.status === 'error' ? 400 : 200 }
    )
  }

  try {
    const session = await login(submission.value)
    console.log('hi')
    if (!session) {
      return json(
        { status: 'error', result: submission.reply() },
        { status: 400 }
      )
    }

    const toastSession = await getToastSession(request)
    toastSession.flash(SESSION_MESSAGE, `Login successful!!!`)

    const headers = new Headers()
    headers.append('Set-Cookie', await commitToastSession(toastSession))

    return redirect('/dashboard', { headers })
  } catch (err) {
    return json({
      result: submission.reply({
        formErrors: [(err as Error).message],
      }),
      status: 400,
    })
    // if (err instanceof BadRequestError || err instanceof NotFoundError) {
    // }
    // throw err
  }
}

this is the branch if u wanna see full code -> https://github.com/deadcoder0904/conform-remix-login/tree/test

bold spruce
#

you need to check your component logic + the login function logic and see whats wrong in their