How to use React Hook Form with Material UI
React Hook Form recently won the Productity Booster Award at React Summit so if you are not familiar with React Hook Form, now is a good time to learn it. React Hook Form is performant, has great docs and it works everywhere (including React Native).
Material UI continues to be the most popular open source React component library out there.
So if you are a React developer, there is a good chance you will find yourself with the opportunity to use Material UI's form components with React Hook Form.
A basic TextField#
If you are working with forms in Material UI, you are most likely working with the TextField component like this one:
Enter your name
import { TextField } from '@mui/material';
const BasicTextField = () => {
return <TextField id="name" helperText="A basic TextField component" />;
};
export default BasicTextField;
Add React Hook Form#
If you follow the React Hook Form docs, you will see code that looks like this:
<input name="example" ref={register} />
This doesn't quite work out of the box with Material UI's TextField
component. Instead, we need to make use of the inputRef
prop on TextField
as demonstrated in this example.
import { useState } from 'react';
import { TextField } from '@mui/material';
import { useForm } from 'react-hook-form';
interface Inputs {
name: string;
}
const HookedTextField = () => {
const [name, setName] = useState<string>();
const { register, handleSubmit } = useForm<Inputs>();
const onSubmit = async (data: Inputs) => {
setName(data.name);
};
return (
<>
<form onSubmit={handleSubmit(onSubmit)}>
<TextField inputRef={register} id="name" name="name" helperText="Enter your name and press [Enter]" />
</form>
{name && <div>Submitted: {name}</div>}
</>
);
};
export default HookedTextField;
Reset the form#
Sometimes you need to manually reset form state. React Hook Form makes this easy.
const { register, handleSubmit, reset } = useForm<Inputs>();
const onSubmit = async (data: Inputs) => {
setName(data.name);
reset();
};
Watch fields#
React Hook Form also provides the watch
function that allows you to immediately respond to changes in form state.
const { register, handleSubmit, watch } = useForm<Inputs>();
// This field will update as the user types
const currentName = watch('name');
Putting it all together#
import { useState } from 'react';
import { TextField } from '@mui/material';
import { useForm } from 'react-hook-form';
interface Inputs {
name: string;
}
const FinalTextField = () => {
const [name, setName] = useState<string>();
const { register, handleSubmit, reset, watch } = useForm<Inputs>();
const currentName = watch('name');
const onSubmit = async (data: Inputs) => {
setName(data.name);
reset();
};
return (
<>
<form onSubmit={handleSubmit(onSubmit)}>
<TextField inputRef={register} id="name" name="name" helperText="Enter your name and press [Enter]" />
</form>
<div>
{currentName && <div>Current: {currentName}</div>}
{name && <div>Submitted: {name}</div>}
</div>
</>
);
};
export default FinalTextField;
React Hook Form provides several other options for form management. When paired with Material UI, constructing forms doesn't get much easier.
Are you using React Hook Form with Material UI? Let me know on Twitter.
Looking for help with a development or design project?
Reach out to work with me or other senior-level talent.
Contact me