fgerschau / comments

1 stars 0 forks source link

react-hooks-form-validation-typescript/ #16

Open utterances-bot opened 3 years ago

utterances-bot commented 3 years ago

Form validation with React Hooks WITHOUT a library: The Complete Guide

In this article, I walk you through the process of creating a hook that you can use for managing forms without the use of a library.

https://felixgerschau.com/react-hooks-form-validation-typescript/?utm_campaign=form-validation-with-react-hooks-without

vasiliy-l commented 3 years ago

Thank you for this tutorial! It's a great example I was looking for; clear and simple to get the idea. I'm currently thinking about some easy approach for dynamic forms, where users can add/remove fields before submitting the form data. What do you think if I store the options for the hook as an object and modify the validations property when updating the form fields? Is this idea good enough or it's better to look for some other solution?

fgerschau commented 3 years ago

Hey @vasiliy-l, I'm not sure if I understand exactly how you want to do this. I'd probably start by exposing setData or some other helper function that allows you to add or remove fields to the form data object.

deyvisonborges commented 3 years ago

very good man

teddy-mczieuwa commented 3 years ago

your syntax here confuses me

const [data, setData] = useState(options?.initialValues || {});

what does ?. do? Is it specific to typescript. I got lost on the second line of the useForm code

fgerschau commented 3 years ago

@teddy-mczieuwa the question mark is the optional chaining operator, which is also available in es6

TXredking commented 3 years ago

Great example and walkthrough!

I've run into the following Typescript errors within the handleSubmit function: 1) Since the key from validations is an implied type of Extract<keyof T, string> it can't be used to index the newErrors type of {} 2) newErrors type of {} is not assignable to type SetStateAction<ErrorRecord<T>>

The following changes seem to resolve those errors: 1) Declare newErrors variable instead like this const newErrors: ErrorRecord<any> = {} 2) Change ErrorRecord type definition to type ErrorRecord<T> = Partial<Record<keyof T, string>>;

If there are better solutions let me know!

Chelny commented 2 years ago

Nice job! Checkboxes and radio buttons validation should also be supported.

Only the value attribute is checked here.

const value = sanitizeFn ? sanitizeFn(e.target.value) : e.target.value;

Would be nice is the checked attribute is also checked.

fgerschau commented 2 years ago

@TXredking it can also be resolved by casting the empty object to the error type. I did this in the GitHub repository, but didn't highlight it in the article.

const newErrors = {} as ErrorRecord<T>;

This solution has the advantage that we don't need to modify the original type or use any.

EDIT: I clarified this issue in the article here. I'm not sure anymore whether this is the best approach, though. I also like making the error type partial, as you suggested in solution 2.

EDIT 2: I changed the article and the example code to solution n. 2, it makes it easier to use, and I already used the same approach for the validations type (type Validations<T extends {}> = Partial<Record<keyof T, Validation>>;).

fgerschau commented 2 years ago

@Chelny good point! Did you add support for this? PRs to the example project are welcome :smile:

arunmmanoharan commented 2 years ago

Hi, I would like to get handleKeyDown implemented the same way. For example, I want to add a "\n\r" only when the enter key is pressed. I tried referencing the handleChange in the handleKeyDown method with the modified value but doesnt seem to work as the event is not being sent. Can you please advice?

This is my sandbox: https://codesandbox.io/s/affectionate-framework-44exw?file=/src/App.tsx

marcelo-bottoni commented 2 years ago

Awesome tutorial!

I'm using this approach together with a set of custom input components that I'm creating. This validation idea fits perfectly with that I was building here.

I'm also working on changes in the hook to allow me to do what @vasiliy-l, asked for. I'll share this here if I succeed on it.

jhonsore commented 2 years ago

Hi folks!

First of all thanks for this tutorial, it helped me a lot.

I got an issue and want to share with you guys.

If we put an optional property in User interface like in (password?):

interface User { name: string; age: number; email: string; gender: Gender; password?: string; }

We got the following error :

Type 'User' does not satisfy the constraint 'Record<keyof User, any>'. Property 'password' is optional in type 'User' but required in type 'Record<keyof User, any>'.

We can ride of this error inserting a Partial in useForm hook (line 22), like this:

export const useForm = <T extends Partial<Record<keyof T, any>> = {}>

Wish u All the best!

cuginoAle commented 1 year ago

Hi, interesting article! The thing is that in my experience you don't need to write all that code. It is great that you don't use any library but I don't think we should implement form validation using the controlled components. Manually handling the state and validity of all the form elements is like reinventing the wheel. We already have that built-in in the browser.

I wrote an article to describe just that: https://medium.com/@alessio.carnevale/form-validation-submission-in-vanilla-react-no-libraries-491327f985d0

Your perspective on this approach would be really appreciated!