Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep errors while submiting to the server #121

Closed
andresgutgon opened this issue Jun 15, 2024 · 19 comments
Closed

Keep errors while submiting to the server #121

andresgutgon opened this issue Jun 15, 2024 · 19 comments

Comments

@andresgutgon
Copy link
Contributor

What?

Hi, I'm using useServerAction to save some data into my server. It's working fine but I see a glitch while isPending

The errors in the server are reset and the UI jumbs.

This is my form:

  const { data, executeFormAction, isPending, error, ...rest } = useServerAction(
    onboarding,
    {
      initialData: { name, username },
    },
  )
  const errorData = error?.data
  const fieldErrors = error?.fieldErrors
  return (
      <Input
        label='Your username'
        type='text'
        name='username'
        errors={fieldErrors?.username}
        defaultValue={data?.username ?? errorData?.username}
        onChange={(e) => setUserName(e.target.value)}
        placeholder='Pick a username'
        description={<UsernameDescription username={currentUsername} />}
      />
  )

This is my action:

export const onboarding = authProcedure
  .createServerAction()
  .input(input, { type: 'formData' })
  .output(input)
  .experimental_shapeError(({ err, typedData }) => {
    if (err instanceof ZSAError && err.code !== 'INPUT_PARSE_ERROR') {
      return {
        code: err.code,
        message: err.message,
      }
    }

    return {
      data: typedData?.inputRaw,
      fieldErrors: typedData?.inputParseErrors?.formattedErrors,
    }
  })
  .handler(async ({ input, ctx: { user } }) => {
    await validateUniqueUsername({ data: input, user })

    const result = await finishOnboarding({ user, data: input })
    const value = result.unwrap()
    await updateSession({
      user: { name: value.name, username: value.username },
    })

    redirect('/')
  })

This is my UI. Check the disappearing red errors when submitting

Screen.Recording.2024-06-15.at.16.09.36.mov
@andresgutgon
Copy link
Contributor Author

Am I using it ok? Is there a way of avoiding this glitch?

@andresgutgon
Copy link
Contributor Author

Also, to keep previous data, I had to use shapeError and get typedData?.inputRaw. How hard would always be to return data already present in the form?

I say this because otherwise, all inputs are empty when one of them have a validation error no?

@IdoPesok
Copy link
Owner

Hi, thanks for bringing this up!

I understand the issue. Going to compare with other libraries and report back shortly with next steps.

In the meantime -- if you want to try -- you should be able to get this persistence with useActionState. This also supports progressive enhancement.

always be to return data already present in the form?

Do you mean to return inputRaw in a default TZSAError without needing to do shape error?

@andresgutgon
Copy link
Contributor Author

Do you mean to return inputRaw in a default TZSAError without needing to do shape error?

Yes!

@andresgutgon
Copy link
Contributor Author

Using state gives me this TS error

I'm in latest zsa. In fact I'm debugging it locally with npm link
image

@IdoPesok
Copy link
Owner

What version of React is this?

@IdoPesok
Copy link
Owner

Also if you are using npm link, do you want to give the input schema functions a shot? Going to merge soon would be awesome if you can test that branch in your project and give feedback.

@andresgutgon
Copy link
Contributor Author

andresgutgon commented Jun 15, 2024

What version of React is this?

I'm living on the edge xD

{
    "next": "14.3.0-canary.59",
    "next-auth": "5.0.0-beta.19",
    "react": "19.0.0-beta-26f2496093-20240514",
    "react-dom": "19.0.0-beta-26f2496093-20240514"
}

Maybe is because of types?

    "@types/react": "^18.2.61",
    "@types/react-dom": "^18.2.19",

@andresgutgon
Copy link
Contributor Author

Also if you are using npm link, do you want to give the input schema functions a shot?

I can try that. But would be ideal to use useServerAction

And out of the box get:

  1. data persisted between attempts
  2. Do not erase errors until the response come from the server (action)

But I think that would be ideal without needing to customize errors or other parts of the lib. It would make a straightforward understand of the model

@IdoPesok
Copy link
Owner

Ah yes, I meant outside of this issue and related to #120 so you don't need to do validate unique username in the handler.

@andresgutgon
Copy link
Contributor Author

Ah!! yes yes I didn't understand you. Let me check that

@IdoPesok
Copy link
Owner

Hi, the formatted errors come from Zod formatted errors. Same thing with field errors, and form errors. These are standard Zod error schemas that people use. We can be more clear in our docs to explain this.

@andresgutgon
Copy link
Contributor Author

andresgutgon commented Jun 16, 2024

I see, but my question is. For having formatted errors do I need to use shapeError. I'll try with stable branch but i think it's working without that method

It does indeed. And also in your PR. All was my fault #121 (comment)

@andresgutgon
Copy link
Contributor Author

andresgutgon commented Jun 16, 2024

Playing with this #120 is failing for me

Basically I'm not sure what I have to pass in the input
I'm passing a z.object but is failing

input(async ({ ctx }) => z.object(...), { type: 'formData'})
image

I see this in Chrome Dev tools
image

I think that PR could have a regression

The same code in my app gets the error on error key from useServerAction hook
image
image

But with that PR I get the error about my ZodObject not being an instance of z.ZodType. No idea what could be wrong. My ZodObject is indeed an instance of zodType

@andresgutgon
Copy link
Contributor Author

andresgutgon commented Jun 16, 2024

Doing these 2 changes it works. No need for custom shapeError

Looks like something related with instanceof but no idea why these 2 return false

image

@andresgutgon
Copy link
Contributor Author

andresgutgon commented Jun 16, 2024

Maybe is related colinhacks/zod#2241 or this one colinhacks/zod#2746

@andresgutgon
Copy link
Contributor Author

andresgutgon commented Jun 16, 2024

ALL_MY_FAULT 😂

Oh man, NodeJS is hard.
What happened is your monorepo use NPM and I was linking from my monorepo with pnpm link ~/code/opensource/zsa/packages/zsa and it was taking Zod from pnpm and so the instance was different when checking instanceof

What I did instead is

{
  "zsa": "file:../../../../opensource/zsa/packages/zsa",
  "zsa-react": "file:../../../../opensource/zsa/packages/zsa-react",
}

Fuck, this was a good lesson.

Your PR works great input(function) does what it promise 🎉

image

I'll move now to investigate the problems in this issue

OFF-TOPIC:
What's the use case for retry? Reading the code it makes everything more complicated. I'm curious to know what made you implement retries in this package. I can't imagine any good cases

@IdoPesok
Copy link
Owner

Sorry for late response, was traveling this wknd!

Oh man, NodeJS is hard. What happened is your monorepo use NPM and I was linking from my monorepo with pnpm link ~/code/opensource/zsa/packages/zsa and it was taking Zod from pnpm and so the instance was different when checking instanceof

Ah this is super tricky! I was so confused why the instance of wasn't getting the ZodObject in your first message. Good job debugging this.

Your PR works great input(function) does what it promise

Awesome! Happy to hear! Still writing some more tests. Excited to merge it.

What's the use case for retry?

Sometimes if there are rate limits in effect it could be useful to retry. This is also available in libraries such as react-query. I agree it does make things more complicated 😄 I had a branch with many more features such as polling and caching but figured people just should use react-query with zsa since its already so good.

Okay, I am going to move this conversation to #124 as the code is there.

@andresgutgon
Copy link
Contributor Author

Polling and caching

Yep, these are frontend concerns and because zsa already integrates with react-query there's no need to bring that complexity to this code.

Okay, I am going to move this conversation to #124 as the code is there.

Nice, happy to change anything

Repository owner locked and limited conversation to collaborators Jun 22, 2024
@IdoPesok IdoPesok converted this issue into discussion #143 Jun 22, 2024

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants