is it worth it to have meaningful errors returned from server side form validation?
like is it worth it at that point to return an error for every field that is invalid from the backend or should you just throw a bad request
assuming you already have full validation on client side
like if someone does somehow bypass client validation lets say by disabling javascript is it even worth it to have meaningful server errors for every field
i can see the argument for progressive enhancement but like if you want to have good ux on forms it feels like you almost always need javascript
63 Replies
so the way i generally handle this, is to do validation on the backend, but just return a 400 to the client, and let your JS do the actual form validation
now, if your trying to make a standalone API that you want people to use, maybe you could argue it would be nice for people trying to use your api to see whats going wrong, but generally youll just be sending 400's
Imo, if you expect the whole form to be submitted at once and don't have some form of partial updates/a complex form that is separated in multiple parts, I don't think there is a reason to validate every single field tbh. You validate the whole form, if something doesn't validate throw a generic
Bad Response
with some generic message. And if you have some fields that have additional logic attached to them, you can validate those separately and if they fail, throw a more specific Bad Request
. That is how we handle most of our form validation via the BEIf specific fields need specific inputs, like say you need to input a product code in a specific format or something, then ill usually do per-field validation just for a nice UX, but this is always better solved with some sort of form library instead of trying to do it yourself
i agree with these points. is disabling javascript all that common? trying to see this from the progressive enhancement side
if your using react and they disable javascript your site wont work anyways iirc
assuming your using react
well, the client components wont render
This isn't just about "disabling JS though". Is your API public? Is it gonna be consumed from other clients as well? Or is it something that is only used by your app. Because that makes a major difference in how you approach all of this.
Yeah, that is what I meant. If you have some specific logic tied to a field, you validate for that specific field additionally.
that and per field validation for hey this field is required and you left it blank
Ah, fair. Yeah, we use GQL at work and I haven't build a non-GQL API for a while. Thus I didn't consider validating required fields
disabling js is very common for webscrapers and some headless browsers (cli browsers), but if someone is visiting your site like that they probably arent going to the forms anyways
im in a weird spot with one of my contracts where the client kinda knew python and specifically wanted me to build our backend in python with a standalone react frontend so the stack is a complete mess. Needless to say i dont have the fancy tools like gql
but now we are at 16k loc and he gave up trying to understand it so im trying to slowly convert parts of it to next / literally anything other than python
Uhhhh, are there no gql libs for Python? That sucks honestly
Yeah, if it's such a small project, you can easily convert it to something like TRPC even, if you don't need the separate BE
oh shit there is
although tbh i dont think gql would be very helpful for most of my shit
Yeah, tbf gql isn't the easiest to implement properly
most of our app is very large chains of complex ish logic with tons of side effects
And you can easily fuck yourself over
right
im pretty comfy with where its at now, i just wish pythons type system was actually good
You mean it actually existed. Cuz just becuase there is a lib about it, doen't mean it's there.
ill just throw this out there: i think there ar e2 kinds of errors
theres errors like 'your first name shouldnt have a number in it' that can be caught with validation on the client side
but then there are errors that are like 'you cant create an account if you already have one' where only the server can really validate it
personally i think zod + trpc is one of the best parts of the t3 stack because it gives me a way to send both kind of errors. my client can then figure out how to put those errors in relevant spots
but IMO the validation should always be done by the server anyway cause otherwise you could end up with garbage in your db (either from unknowing api users or malicious actors)
how do you guys choose to validation on client side? onChange of every field or onSubmit? i really dont know what most users prefer
deff not onchange. use a form lib of some sort, they usually have good error handlers built in
thinking of using react-hook-form rn
wondering why you prefer onsubmit over onchange?
i dont think ive used it yet, but ive heard very, very good things ab it
if you use onChange, then the user will always see an error either at the beginning of the form, OR while they are typing
i prefer onsubmit as well. with good labels and information to guide the user into putting correct info. but just wanna see other perspectives
onSubmit will only show errors when the user has actually tried to submit something errorful
yepp
agreed
to do really good error management youll find you need a rediculous amount of state management just ot make it look nice
aka, use react-hook-form
yea. most of the time overkill. but yea i agree
i use rhf + zod, but IMO rhf is like.... really good for really basic forms
i dont have a better alternative
but my app has a lot of pretty dynamic forms and rhf basically acts as its own store you have to communicate with
cause it does everything with uncontrolled inputs
that said. the fact that it uses uncontrolled inputs makes the performance wayyyyyy better
is that a problem when you have inputs that are dependent on eachother?
wdym?
just started using rhf so im not sure if its even related but im thinking of validation where one input might be dependent on another
you can do validation like that thru zod with refine / superRefine
my problems are more like 'you picked x so i need to get that value, do some transforms on it and display y'
ahhh okay i see. are the docs a good enough learning resource? i usually look for vids but not sure if theres any up to date ones
i dont mind the zod docs. i havent needed to look anywhere else for that
the rhf ones are a lot more meh
mb i mean the rhf ones. zod ones are pretty decent
i think the rhf docs are ok. its just when you get into some of the nitty gritty
the biggest things ive struggled with are:
1) you can have optional values in your zod validator, but none of the rhf functions can take undefined as a value
this is further made confusing because defaultValues are all defined as
DeepPartial<YourValidatorType>
so your default values can all be undefined
2) it doesnt solve some of the basic stuff around like things like making a textbox only allow number inputs
you still gotta deal with the raw html props for that
3) since it maages its own state you sometimes have to do werid things with watch()
, or useEffect()
to sync the state of what is rendered in your form with the state of the form itself
there are escape hatches for a lot of things, but i have a hard time wrapping things in nice patterns
ive also hit some of the real edge cases of it cause my app has a few very large, very dynamic formsdef gonna keep an eye out for this. interesting
with a lot of logic
do you prefer to handle errors on submit or onchange?
the default with rhf is pretty good. the errors dont show up until you submit the form, then everything is onchange
cause people hate to be told theyre wrong while theyre still in the middle of typing
for some of the heavier forms that need to do heavy logic when some of the fields change i use the onBlur option instead
bt thats purely because of performance
for your large forms, do you split them into multi part forms?
multi part forms are usually a better ux im thinking?
i opted for tabs. the thing is my forms are really big, but theres defaults for most of it
so its very customizable, but if you want you can just click submit and it will work
interesting. i guess thats like a multi part form but without "steps"?
yeah
if you want you can try it
https://truefinals.com/create
youll need to make an account tho (i reccomend signing in with google cause i do have actual email verification and stuff)
that looks pretty dope. is that MUI?
some mui components for the inputs and buttons and icons. layout is all just tailwind
very sleek look. def gonna take a peek inside
ty
still wip
does your forms persist with network loss / refresh?
not refresh. network loss is fine
wondering if rhf supports that with like localstorage or whatever
it might
is this prod ready? do you have mau?
kinda. im using it with some beta users
hoping to start marketting it sometime this summer
hardest fukin part lol. marketing.
yeah well
ill find out
yup. its a learning process. definitely the most important part of any app
yeah well hopefully i can find some people to do that for me
definitely going to hit you up later this summer if you dont mind. would love to see if you have any learnings from that stage whenever you get to it. its what i struggle with most
yeah well ill also say like.... im probably not a great example on that front
basically i found 1 enterprise customer before i even started working on this
so like no matter what as long as i land that 1 user the app will be worth it
and i already have (although im still working thru contract negotiations)
but theyre already using it
yea thats fair enough. everything else is extra for you
yeah