The complete type-safe
material-ui
and react-hook-form
combo and beyond with simple api.
Highly Customizable
and supports 99% use-cases
Click here to see a live example!
Before Installing we need to install material-ui & react-hook-form
For date pickers
npm install @mui/x-date-pickers
---- or ----
yarn add @mui/x-date-pickers
Then Install
npm install mui-react-hook-form-plus
---- or ----
yarn add mui-react-hook-form-plus
If you are familiar with react-hook-form
you will love it! Otherwise, you will also love it 😻
We use propGetter
pattern just like react-hook-form
is doing by registering
the state
of each field.
- Import
Components
andHooks
formmui-react-hook-form-plus
. - From
useHookForm
get theregisterState
method. - Call the
registerState
method withname
asargument
that you want toregister
thefield
to withspread operator
.
For more clear-cut answer follow
the example below:
import { HookTextField, HookRating, useHookForm } from 'mui-react-hook-form-plus ';
const Component = () => {
const defaultValues = { name: 'Adiat Hasan', rating: 4 };
const { registerState, handleSubmit } = useHookForm({
defaultValues,
});
const onSubmit = (data: typeof defaultValues) => {
// will run if it is valid
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<HookTextField {...registerState('name')} />
<HookRating {...registerState('rating')} />
<button type='submit'>Submit</button>
</form>
);
};
We have awesome typescript
support so that you can take the most of it. Also, validation
is a piece of 🧁(cake)
Add rules
prop to your [InputComponents]
import { HookTextField, useHookForm } from 'mui-react-hook-form-plus ';
const Component = () => {
const defaultValues = { name: '', isAdmin: true };
const { registerState, handleSubmit } = useHookForm({
defaultValues,
});
const onSubmit = (data: typeof defaultValues) => {
// will run if it is validated | if !valid will thrown error in the UI
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<HookTextField
{...registerState('name')}
rules={{
required: {
value: true,
message: 'A required field',
},
// maxLength
// minLength
// pattern
// validate -> Fn -> reutrn -> srting | undefined
}}
/>
<button type='submit'>Submit</button>
</form>
);
};
It will validate
based on validation rules
we specify.
The onSubmit
Fn
will be triggered if all input === valid
For more options for rules look into this
Now what if we want our vanilla
<input />
?
Just use the register
method not the registerState
import { HookTextField, useHookForm } from 'mui-react-hook-form-plus ';
const Component = () => {
const defaultValues = { name: 'Adiat Hasan', rating: 4 };
const { registerState, handleSubmit, register } = useHookForm({
defaultValues,
});
const onSubmit = (data: typeof defaultValues) => {
// -> do something with the data
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('rating')} />
<HookTextField {...registerState('name')} />
<button type='submit'>Submit</button>
</form>
);
};
You might be wondering what about deep nested
complex Component
?
Use the FormContext
to make it simple.
- Wrap your form with
HookFormProvider
- Pass the methods returned from
useHookForm
toHookFormProvider
- Get the
registerState
method anywhere in thetree
fromuseHookFormContext
Example for Nested Component
import { HookTextField, useHookForm, HookFormProvider } from 'mui-react-hook-form-plus ';
const Component = () => {
const defaultValues = { firstName: '', lastName: '', sex: '', rating: 3.5 };
const methods = useHookForm<Person>({
defaultValues,
});
const { registerState, handleSubmit } = methods;
const onSubmit = (data: Person) => {
// do something
};
return (
<HookFormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmit)}>
<HookTextField {...registerState('firstName')} textFieldProps={{ label: 'First Name' }} />
<HookTextField {...registerState('lastName')} textFieldProps={{ label: 'Last Name' }} />
<NestedComponent />
<button type='submit'>Submit</button>
</form>
</HookFormProvider>
);
};
Now we can get the registerState
without prop drilling
import { HookRating, useHookForm } from 'mui-react-hook-form-plus ';
const NestedComponent = () => {
const { registerState } = useHookFormContext<Person>();
return <HookRating {...registerState('rating')} ratingProps={{ precision: 0.5 }} />;
};
Note that using FormContext
can lack in performance as it is built on top of React.Context
.
To optimize it further and for learning more check out this
We baked in <Grid/>
directly into the [InputComponents]
so that it enhances the DX
.
A gridProps
is what you need to lay out the [InputComponents]
.
But don't forget to Wrap
it inside a <Grid Container/>
import { Button, Grid } from '@mui/material';
import { HookTextField, HookRating, useHookForm } from 'mui-react-hook-form-plus ';
const Component = () => {
const defaultValues = { name: '', rating: 4 };
const { registerState, handleSubmit } = useHookForm({
defaultValues,
});
const onSubmit = (data: typeof defaultValues) => {
// will run if it is valid
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Grid container spacing={3}>
<HookTextField
{...registerState('name')}
gridProps={{
xs: 12,
md: 5,
}}
/>
<HookRating
{...registerState('rating')}
gridProps={{
xs: 12,
md: 5,
}}
/>
<Grid>
<Button type='submit' variant='contained'>
Submit
</Button>
</Grid>
</Grid>
</form>
);
};
You need to install 3 different types of package to make the pickers work:
- The component (@mui/x-date-pickers) manages the rendering.
- The date-library (moment, dayjs, ...) manages the date manipulation.
- The adapter (@date-io) exposes your favorite date-library under a unified api used by component. First you have to install the date-library you want to use to manage dates, and the component package:
// Install component (community version)
yarn add @mui/x-date-pickers
// Install date library (if not already installed)
yarn add date-fns
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { HookDatePicker } from 'mui-react-hook-form-plus ';
const Component = () => {
return (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<form onSubmit={handleSubmit(onSubmit)}>
<HookDatePicker {...registerState('trialEndsAt')} />
</form>
</LocalizationProvider>
);
};
<HookToggleButtonGroup />
<HookAutoComplete />
<HookRadioButton />
<HookTextField />
<HookCheckBox />
<HookSelect />
<HookSwitch />
<HookRating />
<HookSlider />
Check out Inputs Demo
<HookDatePicker />
<HookStaticDatePicker />
<HookDesktopDatePicker />
<HookMobileDatePicker />
Check out DatePicker Demo
<HookDateTimePicker />
<HookStaticDateTimePicker />
<HookDesktopDateTimePicker />
<HookMobileDateTimePicker />
Check out DateTimePicker Demo
<HookTimePicker />
<HookStaticTimePicker />
<HookDesktopTimePicker />
<HookMobileTimePicker />
Check out TimePicker Demo
useHookForm
useHookFormContext
HookFormProvider
As we have promised
with the project name
with adding a -plus
to mui-react-hook-form-plus
.
We delivered it. A few effortless hooks to make your mui
journey special
.
We provided the same pattern
as register
and propGetters
as the form
components
Those Hooks are:
useMenu
usePagination
useAccordion
useTabs
useDialog
useBackdrop
useBottomNavigation
And more hooks
are in lab 🧪 preparing to be released. So, stay tuned.
Check out Hooks Demo
Just follow the CONTRIBUTING.md
& you are good to go.