if value in <Formic initialVales> is undefined React throws error
Warning: A component is changing an uncontrolled input of type text to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://fb.me/react-controlled-components
in input (created by Field)
const InnerForm2=()=>(
<Form className={styles.Form}>
<Field type={"text"} name={"clusterName"}/>
</Form>
)
...
<Formik
validate={this.validate as any}
validateOnBlur
onSubmit={values => console.log(values)}
initialValues={{clusterName: undefined,type:1}}
component={InnerForm2 as any}
/>
...
with undefined value <input /> rendered _without_ value attribute and first update causes value rendering and this throw error
Correct. You must initialize values just as you would with React state
@jaredpalmer This is fine for fields of type string (I'm using Typescript), you can initialize as an empty string. But for inputs of type number, you have to use an initial value of null or undefined if you don't want a value to appear in the input by default. And this continues to show the "uncontrolled input" warning.
Here is my code:
export interface InvoiceLevelTotal {
amount?: number;
currency?: string;
}
export enum FormKeys {
Amount = 'amount',
Currency = 'currency'
}
const formSchema: Yup.ObjectSchema<InvoiceLevelTotal> = Yup.object().shape({
amount: Yup.number().required('Amount is required'),
currency: Yup.string().required('Currency is required')
});
const initialFormValues: InvoiceLevelTotal = {
amount: undefined,
currency: ''
};
<Formik
initialValues={initialFormValues}
onSubmit={(values, { resetForm }) => {
this.addInvoiceLevelTotal(values);
resetForm();
}}
validationSchema={formSchema}>
{(formProps: FormikProps<InvoiceLevelTotal>) => (
<Form>
<Field
name={FormKeys.Amount}
render={({ field, form }: FieldProps<InvoiceLevelTotal>) => (
<input
className="input-block-level"
maxLength="20"
{...field}
/>
)}
/>
<Field
name={FormKeys.Currency}
render={({ field, form }: FieldProps<InvoiceLevelTotal>) => (
<input
className="input-block-level"
autoComplete="off"
{...field}
/>
)}
/>
</Form>
)}
</Formik>
Maybe you can try to write:
amount?: number | string;
and in the _initialFormValues_:
amount: '',
@jaredpalmer How would you handle this, when initial values are undefined or null?
The approach of amount?: number | string; doesn't work well, if you have to do conditional rendering of form elements depending on this value.
props.values.fieldName > 1 would return an error initially as this is a string.
Although this issue was closed we had to handle this situation as well. We did this (TypeScript) :
initialValues={{myfield: '' as unknown as number}}
Not very elegant but it does the job.
I fixed it using render approach in javascript
<Field name={name}
render={({field}) => (
<Input
{...field}
value={field.value || ''}
/>
)}
/>
I fixed it using render approach in javascript
<Field name={name} render={({field}) => ( <Input {...field} value={field.value || ''} /> )} />
Thanks Dude 鉂わ笍
Also might be useful when you want to bypass this issue in validation:
vatId: Yup.string().nullable().transform(x => x || null)
.min(8, __.minLength)
.max(25, __.maxLength)
Most helpful comment
@jaredpalmer This is fine for fields of type
string(I'm using Typescript), you can initialize as an empty string. But for inputs of typenumber, you have to use an initial value ofnullorundefinedif you don't want a value to appear in the input by default. And this continues to show the "uncontrolled input" warning.Here is my code: