Nice video, thank you very much. I was looking for some way to integrate the facility of Remix's action functions with Shadcn Form. And, OMG, I didn't realize that Shadcn's Form component was just a Provider and not another HTMLFormElement at all. Good to know it. You got a new subscriber.
I usually create a utility that returns the same format that the validation does, something like return json(createValidationError("email","already exists"))
Hello, first of all thank you for the library and the great youtube tutorial too! I was wondering ... Right now I am struggling for quite some time already on null and undefined values as they appear to be used as strings which messes up zods validation on those. As I am using zod for the first time it took me a while to figure out, that zod.coerce.number().optional() which should accept number | undefined should indeed work correctly, but the main issue as far as I can tell is, that the formData that arrives at the server caused undefined and null to become strings of their values and remix hook form doesnt seem to handle this case before handing the data over to zod. Maybe it's not something that remix hook form *should* handle, but I was wondering if maybe you could guide me to the correct way of dealing with this issue?
The hook on the client and the getValidatedFormData both have a config option called shouldStringify which you can use to either send those values through or not, but to be honest I'm thinking about not sending undefined values at all
@@alemtuzlak yeah I saw that option, I might have to try it out again tomorrow, but if I remember correctly I found it's behavior rather odd, but maybe I didn't understand it correctly. Basically if I remember correctly it turned numbers into a string (makes sense) It once again turned undefined and null into "undefined" and "null" respectively, understandable but no changes from the previous behavior. But now it turned a string like "hello" into "'hello'" a string of the string. I didn't quite understand the usecase of this, but I might be missing some information
Okay I checked again. One option I had to set was the stringifyAll = false option on useRemixForm, as it is true by default. Your comment pointed me to the right direction, thanks! Regarding your opinion to not submit undefined, I think that would probably indeed make the most sense. In fact, coincidentally, an open issue in the repo had some action going on. One developer opened a PR, which does filter "undefined" to not be added to formData. Only difference right now is, that he also does the same for null, which we discussed in the comments, is probably not necessary. Using this small change though, my usecase works and the problem has been resolved. Thanks again for the reply and for the useful library!
I usually prefer doing these kind of things with resource routes and fetchers, another alternative is having two forms with different intents and then having an action differentiate between the two with the intent
@@alemtuzlak thanks Alex for the quick response, i have a follow up question. For example I have two forms on a route(not a single form with multiple actions) then each form have their own set of schema, so i would need to create two instance of RemixHookForm? in the action how would i get the intent because if i use getValidatedFormData i pass the specific schema so i will not be able to check the intent. But if i get first the formData using the "await request.formData" to check the intent, the problem is when getValidatedFormData runs there is an error "body used already for: localhost:XXXX" how would you go about this scenario or this might be a design issue on my part?
11 місяців тому+1
Nice work! I was actually kind of hoping that for example number inputs stay numbers in FormData instances, but no… 😁 Strings, like you said. Regarding validation, would it be fine to return status code of 400 on validation error, or would that break the flow due to error boundaries or whatnot? Super excited that this exists for Remix now, and that the perspective is to get it eventually into react-hook-form itself!
Yeah, I feel ya, this is also the case for anything else, booleans etc. It would, the only difference would be that you get a console.error in the browser that the request was a 4XX or whatever your statusCode is. This was actually one of my first remix OSS, has been around for a while now. I'm working with the react-hook-form team to get all of these things merged into there so you don't have to have a wrapper at all!
Hi Alem, thank you very much for this package. I have been trying to pass a fetcher to useRemixForm and I am obviously doing something wrong because I can’t get it work. Could you please add some content / advice on passing a fetcher please?
Will naturally be doing that in lster parts when I start adding functionalities in. Although you should create a discussion on the repo and I can help out 🙊
Hi AleM 😁I'm testing this solution, it's very amazing, thanks! Shadcn's Form components has accessibility attributes, there is some way to use it with Remix? Thanks!
I think Conform is amazing, if I personally didn't prefer react-hook-form and that ecosystem I would pick conform in a heartbeat. Edmund is doing an amazing job with it and the API is very similar to remix-hook-form. I would definitely recommend it as an alternative if you don't want to use react-hook-form!
I have the task at work of building a site with internationalization with lots of forms. Wow you channel is perfect! I don't like how Next.js tries to lock in to Vercel so Remix it is. I have to deploy to AWS and might use SST. Do you have any opinions/tips for deploying Remix apps?
Thank you so much! Man I wish I could help but haven't done anything with SST yet, although if you're up for it you can ask on the remix discord, there are a bunch of people there that have done stuff like that and would be happy to help!
Setting input values onChange and onBlur has a "controlled inputs" feel to it, but, I noticed that those inputs are not getting a `value` passed to them, so, they don't resemble the "classic" look of controlled components. It kind of felt like an inbetween controlled and uncontrolled.
Yeah it is in-between, it's uncontrolled in a sense that you don't provide the value and yet you store it onChange. I feel like you get the benefit of not having to controll them but the ease of just giving the component a callback
here is a simple implementation of a csv handler that I've created recently: ```ts export const uploadHandler = (): UploadHandler => async ({ data, filename }) => { const chunks = []; for await (const chunk of data) { chunks.push(chunk); } const buffer = Buffer.concat(chunks); // If there's no filename, it's a text field and we can return the value directly if (!filename) { const textDecoder = new TextDecoder(); return textDecoder.decode(buffer); } // either store it in memory and return it or convert to string or whatever you want to do with the file if (filename && !filename.endsWith(".csv")) { return null; } const file = await yourFileHandler(buffer); return JSON.stringify(file); }; ```
- more re-renders due to controlled nature - not very progressive enhancement friendly as they rely on JS - this is a subjective point but a bit more code and logic needed to maintain them and make sure they work properly
@@alemtuzlak I was wondering if uncontrolled is meant to simplify code also. It appears so. The controlled code can get unwieldy and sometimes difficult for me to follow. I like the idea of maximizing a package or framework before adding on another one. I think I will be your partner on uncontrolled going forward. Also, these controlled components cause me two problems in the greater Internet from a usability standpoint: 1) Instant validation means I can't even get a damn letter out before the form starts complaining that my password is not long enough, always vocalizing this in red of how wrong I already am. I think it is too mean. 2) Disabling submit buttons causes issues with password plugins that auto-fill in without triggering the Submit button to become enabled (no keyup). Then you have to manually "add a letter and then delete the letter" to enable the submit button.
@kevint2723 this is so true, hence why the "validate on submit" was invented as a validation partner, even though that's the browser default anyway. Plus any code you don't have to write is code you don't have to maintain!
If there are any errors, react hook form (client side) will show there error and the remix’s action won’t even trigger right ?
Correct, until your data is valid client-side it won't be sent to the server
Cooooll, thanks for the video
@@dragoninfintyskull you're welcome 🤗
@alemtuzlak you probably meant "invalid"?
I'm looking at Remix now after failing to build anything good with Next.js! your videos are a huge help! Thank you!
That is truly amazing to hear! Glad you're enjoying them, will release more in the future! If you have anything you'd like me to cover let me know
The diagrams and explanations before the code are extremely helpful and unique to lots of web dev tutorials out there. Thanks
Thank you Adam!
Thank you Adam!
Nice work on making this package! And also props to you for trying to have it be a part of react-hook-form 🙌
Thank you so much! Hope you enjoyed the video too!
This was extremely well explained, I was looking into how to use shadcn forms with remix and this gave me the perfect path forward :)
Thank you so much! Glad you enjoyed it!
Wow nice to know that you are the creator of Remix Hook form.. thanks. 👍
Thank you! Yeah, among other things, also created remix-development-tools 😅
Awesome .. @@alemtuzlak 🌟
Nice video, thank you very much. I was looking for some way to integrate the facility of Remix's action functions with Shadcn Form. And, OMG, I didn't realize that Shadcn's Form component was just a Provider and not another HTMLFormElement at all. Good to know it. You got a new subscriber.
Thank you so much! Yeah, tbh they threw me for a loop as well when I was just looking into it and then I was like "ooooooh"
You got yourself a new subscriber, sir.
Thank you kind sir 🙏😊
This is super cool! Thank for making this.
Thank you Alex! 😊
U did really great job!
Thank you!
Alem, I just found you. I love Remix. Thanks.
Glad you enjoyed it, thank you for watching!
Solid work! Thank you a lot
Thank you!
Amazing work!!
Thank you 🙏🙏
Great explanation, thanks ✌🏼
Thank you 🙏🏻
Great job Alex, thanks
Thank you Leo! And it's Alem 😅
@@alemtuzlak Sorry, I aways see Alex on Twitter 😅
you are forgiven! this time @@LeoMiranda
Good job! Very useful! 👍
Thank you!
Whats the best way to pass back additional errors (after passing form validation) within the action function back into the react component?
I usually create a utility that returns the same format that the validation does, something like return json(createValidationError("email","already exists"))
Hello, first of all thank you for the library and the great youtube tutorial too!
I was wondering ... Right now I am struggling for quite some time already on null and undefined values as they appear to be used as strings which messes up zods validation on those.
As I am using zod for the first time it took me a while to figure out, that zod.coerce.number().optional() which should accept number | undefined should indeed work correctly, but the main issue as far as I can tell is, that the formData that arrives at the server caused undefined and null to become strings of their values and remix hook form doesnt seem to handle this case before handing the data over to zod.
Maybe it's not something that remix hook form *should* handle, but I was wondering if maybe you could guide me to the correct way of dealing with this issue?
The hook on the client and the getValidatedFormData both have a config option called shouldStringify which you can use to either send those values through or not, but to be honest I'm thinking about not sending undefined values at all
@@alemtuzlak yeah I saw that option, I might have to try it out again tomorrow, but if I remember correctly I found it's behavior rather odd, but maybe I didn't understand it correctly.
Basically if I remember correctly it turned numbers into a string (makes sense)
It once again turned undefined and null into "undefined" and "null" respectively, understandable but no changes from the previous behavior.
But now it turned a string like "hello" into "'hello'" a string of the string. I didn't quite understand the usecase of this, but I might be missing some information
Okay I checked again.
One option I had to set was the stringifyAll = false option on useRemixForm, as it is true by default. Your comment pointed me to the right direction, thanks!
Regarding your opinion to not submit undefined, I think that would probably indeed make the most sense. In fact, coincidentally, an open issue in the repo had some action going on. One developer opened a PR, which does filter "undefined" to not be added to formData.
Only difference right now is, that he also does the same for null, which we discussed in the comments, is probably not necessary. Using this small change though, my usecase works and the problem has been resolved.
Thanks again for the reply and for the useful library!
@@ooga-k1g no worries, i did create it after all
Super useful video Alem and remix-hook-form looks awesome! BTW your handle for X in your UA-cam bio needs updating.
Thanks so much for letting me know, I'll update them soon! I changed it and forgot to update :(
Great content!!!
Thank you so much 🙏😊
@@alemtuzlak welcome. please keep doing more tutorials. it's helping me a lot. can I request some topics?
@@yooujiin ofcourse!
How do we handle pages with multiple form submissions like there is a create and a delete submission?
I usually prefer doing these kind of things with resource routes and fetchers, another alternative is having two forms with different intents and then having an action differentiate between the two with the intent
@@alemtuzlak thanks Alex for the quick response, i have a follow up question. For example I have two forms on a route(not a single form with multiple actions) then each form have their own set of schema, so i would need to create two instance of RemixHookForm?
in the action how would i get the intent because if i use getValidatedFormData i pass the specific schema so i will not be able to check the intent. But if i get first the formData using the "await request.formData" to check the intent, the problem is when getValidatedFormData runs there is an error "body used already for: localhost:XXXX"
how would you go about this scenario or this might be a design issue on my part?
Nice work! I was actually kind of hoping that for example number inputs stay numbers in FormData instances, but no… 😁 Strings, like you said. Regarding validation, would it be fine to return status code of 400 on validation error, or would that break the flow due to error boundaries or whatnot?
Super excited that this exists for Remix now, and that the perspective is to get it eventually into react-hook-form itself!
Yeah, I feel ya, this is also the case for anything else, booleans etc. It would, the only difference would be that you get a console.error in the browser that the request was a 4XX or whatever your statusCode is.
This was actually one of my first remix OSS, has been around for a while now. I'm working with the react-hook-form team to get all of these things merged into there so you don't have to have a wrapper at all!
Hi Alem, thank you very much for this package. I have been trying to pass a fetcher to useRemixForm and I am obviously doing something wrong because I can’t get it work. Could you please add some content / advice on passing a fetcher please?
Will naturally be doing that in lster parts when I start adding functionalities in.
Although you should create a discussion on the repo and I can help out 🙊
Solid work, please how do we reset the form?
You can use a useEffect and reset from useRemixForm, check out the react-hook-form for details
Is it possible to validate a fetcher form as well using this? I'm having trouble making this happen.
I'm not sure, I think it should be possible
Hi AleM 😁I'm testing this solution, it's very amazing, thanks! Shadcn's Form components has accessibility attributes, there is some way to use it with Remix? Thanks!
Hehe now you got it right. Hmm whoch attributes are you talking about exactly? You could probably add them by hand but probably nit a good idea 💡
I`m new to remix. is this here a validation on the serverside or only client?
Both actually!
@@alemtuzlak Hi there, why do we want to validate server side as well? Is it to ensure data integrity? thanks in advance, amazing library btw : )
@@MaxChan-n7y pretty much yes, because at the end of the day you could even make a request through POSTMAN or something to the backend
How do you compare remix-hook-form to the form library conform?
I think Conform is amazing, if I personally didn't prefer react-hook-form and that ecosystem I would pick conform in a heartbeat. Edmund is doing an amazing job with it and the API is very similar to remix-hook-form. I would definitely recommend it as an alternative if you don't want to use react-hook-form!
Thanks
🙏🏻
I have the task at work of building a site with internationalization with lots of forms. Wow you channel is perfect! I don't like how Next.js tries to lock in to Vercel so Remix it is. I have to deploy to AWS and might use SST. Do you have any opinions/tips for deploying Remix apps?
Thank you so much! Man I wish I could help but haven't done anything with SST yet, although if you're up for it you can ask on the remix discord, there are a bunch of people there that have done stuff like that and would be happy to help!
@@alemtuzlak I'll take a look there, and again, thanks for this channel! Super helpful and informative.
@@banafish thank you so much! It's really appreciated!
Setting input values onChange and onBlur has a "controlled inputs" feel to it, but, I noticed that those inputs are not getting a `value` passed to them, so, they don't resemble the "classic" look of controlled components. It kind of felt like an inbetween controlled and uncontrolled.
Yeah it is in-between, it's uncontrolled in a sense that you don't provide the value and yet you store it onChange. I feel like you get the benefit of not having to controll them but the ease of just giving the component a callback
how to upload image and strings in one form (in one action) that is too complex and no one make a video on it yet...
here is a simple implementation of a csv handler that I've created recently:
```ts
export const uploadHandler =
(): UploadHandler =>
async ({ data, filename }) => {
const chunks = [];
for await (const chunk of data) {
chunks.push(chunk);
}
const buffer = Buffer.concat(chunks);
// If there's no filename, it's a text field and we can return the value directly
if (!filename) {
const textDecoder = new TextDecoder();
return textDecoder.decode(buffer);
}
// either store it in memory and return it or convert to string or whatever you want to do with the file
if (filename && !filename.endsWith(".csv")) {
return null;
}
const file = await yourFileHandler(buffer);
return JSON.stringify(file);
};
```
Hello Alem, Is the code for this available? I see your "remix-shadcn-hook-form" repo at github but I do not see the fruit route there. Thanks.
Unfortunately no, these older vids I used to record on throwaway repos 😅😅
Poz iz Francuske Tuzla ❤ Bih
Pozdrav veliki, hvala na podrsci!
Why don't you like controlled components?
- more re-renders due to controlled nature
- not very progressive enhancement friendly as they rely on JS
- this is a subjective point but a bit more code and logic needed to maintain them and make sure they work properly
@@alemtuzlak I was wondering if uncontrolled is meant to simplify code also. It appears so. The controlled code can get unwieldy and sometimes difficult for me to follow. I like the idea of maximizing a package or framework before adding on another one. I think I will be your partner on uncontrolled going forward. Also, these controlled components cause me two problems in the greater Internet from a usability standpoint: 1) Instant validation means I can't even get a damn letter out before the form starts complaining that my password is not long enough, always vocalizing this in red of how wrong I already am. I think it is too mean. 2) Disabling submit buttons causes issues with password plugins that auto-fill in without triggering the Submit button to become enabled (no keyup). Then you have to manually "add a letter and then delete the letter" to enable the submit button.
@kevint2723 this is so true, hence why the "validate on submit" was invented as a validation partner, even though that's the browser default anyway. Plus any code you don't have to write is code you don't have to maintain!
Hi, please i need the source code
Unfortunately I don't hace it for this video 😅
hey, so you are using the Form component from @remix-run/react or the ShadCN one?
Shadcn form component is just a form provider from react-hook-form so it dpeends if I need to use the context or not within the form