I'm working with react-hook-forms and trying to reset all form fields after submit. The problem is that in my case Autoplete accepts objects as a value.
I've tried to set the defaultValue
to {}
, but received the following message:
Material-UI: the
getOptionLabel
method of Autoplete returned undefined instead of a string for {}
Are there any variants how Autoplete could be reset?
Here is a link to the CodeSandbox
I'm working with react-hook-forms and trying to reset all form fields after submit. The problem is that in my case Autoplete accepts objects as a value.
I've tried to set the defaultValue
to {}
, but received the following message:
Material-UI: the
getOptionLabel
method of Autoplete returned undefined instead of a string for {}
Are there any variants how Autoplete could be reset?
Here is a link to the CodeSandbox
Share Improve this question asked Jul 6, 2020 at 16:02 KarenKaren 1,4295 gold badges27 silver badges50 bronze badges 1- Hey Karen, have you seen this example: codesandbox.io/s/react-hook-form-v6-controller-qsd8r which has an autoplete. – Bill Commented Jul 7, 2020 at 12:27
3 Answers
Reset to default 2A little late to the party but here's a solution if anyone else needs it.
Assuming your autoplete is wrapped inside a Controller, all you have to do is explicitly check the value in Autoplete. Refer below for more
<Controller
name="category"
control={control}
rules={{ required: true }}
render={({ field }) => (
<Autoplete
fullWidth
options={categories}
{...field}
// =====================================================
// Define value in here
value={
typeof field.value === "string"
? categories.find((cat) => cat === field.value)
: field.value || null
}
// =====================================================
onChange={(event, value) => {
field.onChange(value);
}}
renderInput={(params) => (
<TextField
{...params}
label={t("product_category")}
error={Boolean(errors.productCategory)}
helperText={errors.productCategory && "Product Category is required!"}
/>
)}
/>
)}
/>
This should do the trick!
I am suggesting you to do in this way
<Controller
control={control}
name={name}
rules={{
required: required,
}}
render={({
field: { onChange, value, onBlur }, // Create a alias for onChange if it's confusing
fieldState: { error }
}) => {
return (
<Autoplete
//Here never use the onInputChange
options={options || []}
getOptionLabel={(option) => {
return option[optionLabel] ? option[optionLabel] : "";
}} /* This [optionLabel] assume it like you want show it from the array */
getOptionSelected={(option, value) => {
return option.id === value.id;
}}
value={value ?? ""} // This value is from the hook form
inputValue={value?.[optionLabel] ?? value ?? ""} // here the option label is 'name' Used nullish coalescing here
onChange={(event, values, reason) => {
if (reason === "clear") {
onChange(null); // This onChange is from the Hook forms
return;
}
onChange(values || null);
}}
renderInput={(params) => (
<TextField
{...params}
label=label
variant="outlined"
size="small"
onChange={(event) => {
onChange(event.target.value); //Hooks onChange
}} // Kindly use the onchange here
InputLabelProps={{ shrink: true }} // will help you to keep it as label always shrinked
error={errors[name] ? true : false}
helperText={
errors[name]?.type === "serverError"
? errors[name]?.message
: errors[name]?.type === "required"
? label + " required"
: ""
}
/>
)}
/>
);
}}
/>
In here while OnChange(MUI) the input value will update on Hook form. That can be reflected in the inputValue = {value?.[optionLabel]}. After you choose one value from the dropdown "Value" prop will be updated. After the reset() is triggered from the hook form All the values are bee 'undefined'. If the value and value?.[optionLabel] both are undefined means nullish will choose the Empty string.
Hope it will be helpfull!
To reset the value of AutoComplete
with reset
of react hook form you should add the value
prop to the AutoComplete, other ways the reset wont function, see the example:
import { useEffect, useState } from 'react'
import {
Autoplete,
TextField,
reset,
} from '@mui/material'
...
const {
...
setValue,
control,
formState: { errors },
} = useForm()
useEffect(() => {
reset({
...
country: dataEdit?.country ? JSON.parse(dataEdit?.country) : null,
})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dataEdit])
...
<Controller
control={control}
name="country"
rules={{
required: 'Veuillez choisir une réponse',
}}
render={({ field: { onChange, value } }) => (
<Autoplete
value={value || null}
options={countries}
getOptionLabel={(option) => option.name}
onChange={(event, values) => {
onChange(values)
setSelectedCountry(values)
setValue('region', null)
}}
renderInput={(params) => (
<TextField
{...params}
label="Pays"
placeholder="Pays"
helperText={errors.country?.message}
error={!!errors.country}
/>
)}
/>
)}
/>