Performant, flexible and extensible forms with easy to use validation.
yarn && yarn start
Thanks goes to all our backers! [Become a backer].
Thanks goes to these wonderful people. [Become a contributor].
📋 Official documentation
Home Page: http://react-hook-form.com
License: MIT License
Performant, flexible and extensible forms with easy to use validation.
yarn && yarn start
Thanks goes to all our backers! [Become a backer].
Thanks goes to these wonderful people. [Become a contributor].
Following up #176 (comment)
The API page of the website is slow. In particular, toggling the two radio buttons under Register options
section induces a noticeable lag of a few milliseconds on both Firefox and Chromium.
See repro screen capture as requested in #176 : https://drive.google.com/file/d/16Z5AdlqTbikv_72mKcgoFM4yPZDKw6z3/view
Keep up the great work. Thanks 👍
Describe the question?
I want an array of "emergency contacts", 3 inputs per contact. So far, useFieldArray docs makes it look like it'd need to call it 3 times (1 per input) per emergency contact.
Does it support adding multiple input on a single useFieldArray()
call? if so, where are the docs on it? Thanks!
Describe the bug
See https://codesandbox.io/s/silly-cdn-95w82
validationResolver
option and submitting the form logs the expected output.validationResolver
option and it will not submit form fields correctly (only the first submit is correct?). It seems validationResolver
is not being passed the full values
object.let's check
e.type
as well, can't doinstanceof Event
due to react-native.
Sound good, we may need to update doc for controller to let developer know that when the value is following shape, they may get unexpected result.
{
target: {
type:any,
value: any,
}
}
Originally posted by @xiaoyu-tamu in react-hook-form/react-hook-form#1092 (comment)
Describe the bug
In the typescript documentation section, the code example seems to be broken in ways that make it hard to understand the API for newcomers like myself.
Notice that in this line, email
and name
are destructured but not referenced elsewhere in the code example. const onSubmit = handleSubmit(({ name, email }) => {}) // firstName and lastName will have correct type.
Is the intention instead to be destructuring firstName
and lastName
?
Moreover, the link to the CodeSandbox seems to be unrelated to the TypeScript example, and doesn't actually use TypeScript.
This is a hook for easy integration of yup as a validation method, using a validation resolver. The hook returns a memoized callback that can act as a validation resolver for useForm
hook:
import { useCallback } from 'react';
const useYupValidationResolver = validationSchema =>
useCallback(
async data => {
try {
const values = await validationSchema.validate(data, {
abortEarly: false,
});
return {
values,
errors: {},
};
} catch (errors) {
return {
values: {},
errors: errors.inner.reduce(
(allErrors, currentError) => ({
...allErrors,
[currentError.path]: {
type: currentError.type ?? 'validation',
message: currentError.message,
},
}),
{},
),
};
}
},
[validationSchema],
);
export default useYupValidationResolver;
It can be used in a form like this:
useForm
hook const validationSchema = useMemo(
() =>
yup.object({
firstName: yup.string().required('Required'),
lastName: yup.string().required('Required'),
}),
[],
);
const validationResolver = useYupValidationResolver(validationSchema);
const form = useForm({ validationResolver });
Errors don't seem to be handled correctly in Gatsby. Upon submission of form, errors aren't being rendered as they are in Create React App.
Here are two sandboxes with largely identical code (taken from the RHF docs), one in CRA and one using Gatsby:
CRA: https://codesandbox.io/s/rough-cookies-6g7jp
Gatsby: https://codesandbox.io/s/elated-hooks-dsls1
Upon submission of CRA form, errors are rendered, upon submission of Gatsby form, nothing is rendered and logging errors yields an empty object.
Describe the solution you'd like
An example of an autosave form with debounce
The form builder is a great feature.
I'm just requesting to take it another level by providing option to generate code according to a third-party library.
For example, I use ant. If I use form builder and copy code, I still have to change the fields according to ant specific fields API. If there is someway I can choose what library I use, and the code sample has code with ant's Input
field and they are registered like you show in Work with UI library
section.
I know there are a ton of UI libraries, but this feature request is just a thought.
"Delete all" in form builder is not working
Hello,
A small message as an introduction: I already poped a thread on Reddit to thank you but I would like to thank you again for that library, this is just so cool! I didn't find any issues that block me right now and that's really crazy!
Here is a small suggestion for Typescript typings, for compatibility with elastic-ui
I had to inject both setValue
and register
function and I know it can be a bit complicated at first glance for Typescript user on How to use it.
Edit: It can be hard to use types from the react-hook-form
library in another part of the application. This suggestions aims to guide people doing it whenever they need it :)
Here is my component interface
import { FormContextValues } from "react-hook-form";
interface Props {
name: string;
defaultChecked: boolean;
label: string;
registerFn: FormContextValues["register"];
setValueFn: FormContextValues["setValue"];
}
I wanted to share the way to get the registerFn signature, maybe we could imagine that in the doc.
Regards,
Andréas
Hi all,
I'm not super familiar with Redux Form, but this code snippet from the Library Code Comparison section of the homepage caught my attention:
Shouldn't this just be checking values.username
, not values.username.length
? Happy to make PR if that's the case - just wanted to check first.
As per our discussion in react-hook-form/react-hook-form#1150, it would be good to have some more explanation about first render and the fact that reset
in a useEffect
can be used to force default values to be available via watch
after mount.
Imho justifies a new FAQ entry. A note on reset
in the API reference also makes sense. 👍
Thanks :)
Hello, some questions about the Controller component :) I guess it could help make things clearer.
I'll also make a documentation pull request.
Imagine we have a custom controlled Switch
component.
To reduce confusion, only allows the <Controller as={Switch} />
syntax and remove the <Controller as={<Switch name="blabla" />} />
one, and always pass full props to that component ?
This also simplifies that
https://github.com/react-hook-form/react-hook-form/blob/bc1abcfba52c97704d01645bc7e8384e2b2aef19/src/controller.tsx#L118
Maybe I'm missing some cases? Like Select? :(
I see that the dependency has not been given.
I guess register and unregister should have name
as deps, isn't? otherwise, we might experience a memory leak?
I usually do kind of thing
useEffect(() => {
if (props.name) {
props.register({ name: props.name });
}
return () => props.unregister(props.name);
}, [props.name]);
Help wanted :)
please help to translate over the website.
we have added two more new features:
https://react-hook-form.com/api#Controller
https://react-hook-form.com/api#ErrorMessage
https://react-hook-form.com/api#control
https://react-hook-form.com/faqs#TestingReactHookForm
https://codesandbox.io/s/6j1760jkjk
Solution:
Change removeFriend method for the next one:
const removeFriend = index => () => {
setIndexes(prevIndexes => [...prevIndexes.filter(item => item !== index)]);
setCounter(prevCounter => prevCounter - 1);
};
a lot of asking how to test with react-hook-form, i think it make sense to share some of the recipes.
I'm using React Semantic UI and I found that for the checkbox the normal return {value: data.value} doesn't work.
I'm not sure if this only happens for React Semantic UI but anyway since I didn't found anything on the documentation regarding this point I will let the solution that I found. So that it can be added to the documentations
const onSwitchChange = ([event, data]) => {
return { checked: data.checked }; // Instead of return { value: data.value };
}
...
<Controller
as={<Form.Checkbox toggle />}
name="CheckboxToggle"
control={control}
label="My Switch"
defaultValue={props.swicthState}
onChange={onSwitchChange}/>
Describe the bug
I'm currently using Controller
with MUI TextField, and it was amazing, but I keep getting this error: Warning: A component is changing an uncontrolled input of type text to be controlled.
, I have to set an empty string to as the default value to solve the problem, which I think it should done it by default.
To Reproduce
Steps to reproduce the behavior:
Controller
with MUI TextField
Codesandbox link
https://codesandbox.io/embed/react-hook-form-controlled-warning-demo-l7k6h?fontsize=14&hidenavigation=1&theme=dark
Expected behavior
No error/warning
Desktop (please complete the following information):
Additional context
A similar issue that i found from react-hook-form-input
: react-hook-form/input#31
To replicate the bug :
result :
expected :
The website/documentation is hard to read for some of us who prefer light color schemes.
Thank you.
I just wanted to provide some more practical uses of the watch API with examples of text input, radio group, and selection dropdowns, as well as the original checkbox example:
https://codesandbox.io/s/react-hook-form-watch-with-radio-buttons-and-select-examples-ttpfz
Describe the bug
react-select components no longer work as documented and shown in https://codesandbox.io/s/react-hook-form-hookforminput-rzu9s
To Reproduce
Steps to reproduce the behavior:
Codesandbox link
https://codesandbox.io/s/react-hook-form-rhfinput-444xe
Expected behavior
Items should be properly selected
Additional context
I know the fix. But that's either an unintentionally introduced bug or a breaking change introduced in a minor version release.
The fix:
- onChange={([selected]) => {
- return { value: selected };
- }}
+ onChange={([selected]) => selected}
In order to make Typescript compiler understand CSS Modules files, We need to generate .d.ts
file in the project so that the compiler won't complain about that.
The simplest solution is creating an global.d.ts
or import.d.ts
file and write like this.
declare module '*.css' {
interface IClassNames {
[className: string]: string
}
const classNames: IClassNames;
export = classNames;
}
but this is not enough. because it's so simple and you won't get the autocompletion from this typing.
There's a way to improve this.
in your doc
https://react-hook-form.com/advanced-usage/#ErrorMessage
I think you meant this:
import React from 'react';
const ErrorMessage = ({ errors, name }) => {
const messages = {
test: {
min: "This field required minLength of 8"
},
required: {
message: '* This field is required.'
}
};
// Note: if you are using FormContext, then you can use Errors without props eg:
// const { errors } = useFormContext();
if (!errors[name]) return null;
console.error("errors", errors);
return <span>{messages[errors[name].type].message}</span>;
};
export default ErrorMessage;
or am I lacking some knowledge about some notation? name is a variable, you cannot just do errors.name and expect javascript to use the variable there.
and messages had the wrong visibility
cheers
Code example of the errors API on the website does not match the one in the code sandbox
Website:
import React from 'react'
import useForm from 'react-hook-form'
function YourForm() {
const { register, errors, handleSubmit } = useForm();
const onSubmit = data => console.log(data)
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input name="singleErrorInput" ref={register({ required: true })} />
{errors.textInput && 'Your input is required'}
{/* refer to the type of error to display message accordingly */}
<input name="multipleErrorInput" ref={register({ required: true, maxLength: 50 })} />
{errors.textInput && errors.textInput.type === 'required' && 'Your input is required'}
{errors.textInput && errors.textInput.type === 'maxLength' && 'Your input exceed maxLength'}
{/* register with validation */}
<input type="number" name="numberInput" ref={register({ min: 50 })} />
{errors.numberInput && 'Your input required to be more than 50'}
{/* register with validation and error message */}
<input name="errorMessage" ref={register({ required: 'This is required' })} />
{errors.errorMessage && errors.errorMessage.message}
<input type="submit" />
</form>
)
}
It has errors, since the fields are referenced as errors.textInput
instead of errors.singleErrorInput
and errors.multipleErrorInput
. On the other hand, codesandbox code is correct:
import React from "react";
import ReactDOM from "react-dom";
import useForm from "react-hook-form";
import "./styles.css";
function App() {
const { register, errors, handleSubmit } = useForm();
const onSubmit = data => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label>Error</label>
<input
type="text"
name="singleErrorInput"
ref={register({ required: true })}
/>
{errors.singleErrorInput && "Your input is required"}
<label>Error with type check</label>
<input
type="text"
name="multipleErrorInput"
ref={register({ required: true, maxLength: 50 })}
/>
{errors.multipleErrorInput &&
errors.multipleErrorInput.type === "required" &&
"Your input is required"}
{errors.multipleErrorInput &&
errors.multipleErrorInput.type === "maxLength" &&
"Your input exceed maxLength"}
<label>Error with value</label>
<input type="number" name="numberInput" ref={register({ min: 50 })} />
{errors.numberInput && "Your input required to be more than 50"}
{errors.numberInput && errors.numberInput.message}
<input type="submit" />
</form>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
original issue can be found here: https://spectrum.chat/react-hook-form/help/useformcontext-and-errors~41a32449-970d-4094-82e2-e4d2564fc64e
Hello,
I have been in constant pain because I did not know, that I have to call formState in order for formState.touched to understand what input has been touched. Is this intended, is it documented? This feels so counterintuitive.
I took this codesandbox(in your website): https://codesandbox.io/s/7o2wrp86k6
And edited it into this: https://codesandbox.io/s/react-hook-form-formstate-dirty-touched-submitted-irclr
You can clearly see I took all the calls to formState away, except the one I need in submit.
And the console.log formState.touched is empty.
Also calling formState does rerender for whole form.
On the https://react-hook-form.com/ website the "Live Demo" section at the bottom doesn't populate touched fields in the "Touched" column.
Describe the bug
When useForm is used with the validationResolver option, and the identity of the resolver function changes, validation will break. Fields are no longer validated. When I hit Submit button, the resolver receives empty data object. In case of onBlur mode, on loss of focus the resolver is not called at all.
The same behavior is manifested when a fresh validationContext object is passed to useForm on every render.
To Reproduce
Steps to reproduce the behavior:
Codesandbox link
https://codesandbox.io/s/react-hook-form-validationresolver-1bzwb
Expected behavior
Validation keeps working. After every keypress, username should be immediately re-validated. The error message should disappear when username is at least 3 characters long. On loss of focus the resolver should be called again (in the onBlur mode). When I hit the Submit button, the onSubmit callback should receive a data object with username value from input field.
Desktop (please complete the following information):
Additional context
The on blur / on input listener is unregistered in useForm.ts line 1138:
useEffect(
() => () => {
isUnMount.current = true;
fieldsRef.current &&
Object.values(
fieldsRef.current,
).forEach((field: Field | undefined): void =>
removeFieldEventListenerAndRef(field, true),
);
},
[removeFieldEventListenerAndRef],
);
The hook enters the "isUnMount" state (which prevents reRender) and stays there forever (which is probably undesired). Listeners are unregistered, but new listeners are not registered for input elements. (Note that the callback returned from this effect is executed when removeFieldEventListenerAndRef changed its identity, which occurs when a different validationResolver function is passed to useForm).
Expected:
Actual (after second render):
Describe the bug
A11y documentation example recommends not rendering an error element unless the error is in form state. That's unfortunate because the error element is referenced by aria-describedby
attribute. That might result in an error, see https://www.hawaii.edu/access/2019/04/17/3-aria-describedby-has-incorrect-id-reference/
Expected behavior
Error element should be hidden with a css property.
PS. Thank you @razh for pointing that out 🥇
The main project process is here : https://github.com/react-hook-form/react-hook-form/projects/1
Just want to make this progress more visible, to avoid any conflicts and to review together for better quality 😉
Now, we have four parts to go :
Let's leave a comment which part you want to work :)
The main project process is here : https://github.com/react-hook-form/react-hook-form/projects/1
a Japanese version of the website
You've already set the i18n-friendly architecture, so perhaps we can leverage this pattern to example codes.
The smart form component from the documentation is not working: https://codesandbox.io/s/react-hook-form-smart-form-component-eqb3n
In the Form
it does not like ...methods
. It yields object is not a function
.
Also; how do you write the Form
component in typescript? It does not accept props
on child
object.
On https://react-hook-form.com/advanced-usage#ErrorMessage
It seems instead of
const ErrorMessage = ({ errors, name, messages }) => {
// Note: if you are using FormContext, then you can use Errors without props eg:
// const { errors } = useFormContext();
if (!errors.name) return null;
return <p>{messages[errors.name][errors.name.type]}</p>;
};
it should be:
const ErrorMessage = ({ errors, name, messages }) => {
// Note: if you are using FormContext, then you can use Errors without props eg:
// const { errors } = useFormContext();
if (!errors[name]) return null;
return <p>{messages[name][errors[name].type]}</p>;
};
Also, on this page: https://react-hook-form.com/api#errors
It says type of errors
object is Record<string, boolean>
but shouldn't it be Record<string, ErrorObjectInterface>
?
Unless I'm missing something, the documentation isn't versioned with releases of this package.
Check out https://www.apollographql.com/docs/react/ for an example, there is a dropdown in the top left to choose what API version you want documentation on.
Staying updated to the latest version isn't always feasible when deploying a minor feature or what have you, and if you're on a previous version and need documentation, it seems like you're completely out of luck at the moment.
Reset with Controller (defaultValues)
react-hook-form/react-hook-form#670
Reset with useFieldArray (defaultValue)
react-hook-form/react-hook-form#960
Describe the bug
When calling remove and append, the expected behaviour would be that one item is removed and one item is appended, but the result is that the removed item is still in the list.
Also when calling remove and insert it throws an exception.
To Reproduce
Steps to reproduce the behavior:
Codesandbox link
https://codesandbox.io/s/react-hook-form-usefieldarray-qkpif
Expected behavior
should be able to call any of these methods on the same event handler and being able to update field array at will.
This is incredibly minor, but I noticed in /advanced-usage#FieldArrays, the link in Note: if your application requires functionality such as: Delete, Insert, Append, Preprend. Here is the link for such implementation. with Controller.
sends you to a codesandbox that appears to have a bug in it.
The codesandbox implements an update
function that seems to be incorrect (throws an error stating Cannot set property 'id' of undefined
).
The implementation currently is:
const update = index => {
const data = getValues();
data[index].id = data[`field${index}`];
setData([...data]);
};
which (unless I've misunderstood what the function is trying to do), should be something like:
const update = index => {
const values = getValues();
const oldId = data[index].id
const newId = values[`field${oldId}`]
setData([...data.slice(0, index), { id: newId }, ...data.slice(index + 1)])
};
Hi, I noticed that there's a typo on the last FAQ question "What if you don't have access to ref?". In the code block, you're importing useRef
instead of useEffect
.
Describe the bug mistake
Hello!
There is a mistake in docs.
You forgot handleSubmit there.
Update useFieldArray section to include information about custom register.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.