In my React Typescript app, there is a Formik form with fields that does not need to be populated with any values (i.e. the placeholder text is visible).
How can we achieve this?
Attempt 1:
In Formik's initialValues
, I tried not defining any values whose form should be empty initially.
<Formik
initialValues={{
itemType: 'any',
}}
...
>
interface Values {
itemType: string;
minPrice?: number;
maxPrice?: number;
}
However, when a user types something into any of these forms, the browser JS console shows the warning:
index.js:1 Warning: A ponent is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the ponent. More info: at input
Attempt 2:
Tried setting these values to null
in Formik's initialValues
prop,
<Formik
initialValues={{
itemType: 'any',
minPrice: null,
maxPrice: null,
}}
...
but TypeScript throws an error:
Type 'string' is not assignable to type 'never'. TS2322
Type 'string' is not assignable to type 'never'. TS2322
66 | <Formik
67 | initialValues={{
> 68 | itemType: 'any',
| ^
69 | minPrice: null,
The React app does not even start!
Full Code
import { Button, Modal, Form, Row, Col } from 'react-bootstrap';
import { Formik, FormikHelpers } from 'formik';
interface Values {
itemType?: string;
minPrice?: number;
maxPrice?: number;
}
export function FormModal({show, handleClose, updateFilter}: IModal): JSX.Element {
return (
<Modal show={show} onHide={handleClose}>
<Modal.Body>
<Formik
initialValues={{
itemType: 'any',
minPrice: null,
maxPrice: null,
}}
validationSchema={schema}
onSubmit={(
values: Values,
) => {
updateFilter(values);
handleClose();
}}
>
{( {values, errors, touched, handleChange, handleBlur, handleSubmit, isSubmitting, setFieldValue }) => (
<Form id="updateFilterForm" onSubmit={handleSubmit}>
<Form.Group as={Row} controlId="formItemType">
<Form.Label column sm="3">Item Type</Form.Label>
<Col sm="9">
<Select
name="itemType"
options={itemTypeOptions}
onChange={option => setFieldValue("itemType", option!.value)}
onBlur={handleBlur}
values={values.itemType}
/>
</Col>
</Form.Group>
<Form.Group as={Row} controlId="formPrice">
<Form.Label column sm="3">Price Range</Form.Label>
<Col sm="9">
<Form.Row>
<Col>
<Form.Control
type="number"
name="minPrice"
onChange={handleChange}
onBlur={handleBlur}
value={values.minPrice}
placeholder="Min"
/>
</Col>
<Col>
<Form.Control
type="number"
name="maxPrice"
onChange={handleChange}
onBlur={handleBlur}
value={values.maxPrice}
placeholder="Max"
/>
</Col>
</Form.Row>
</Col>
</Form.Group>
</Form>
)}
</Formik>
</Modal.Body>
</Modal>
)
}
In my React Typescript app, there is a Formik form with fields that does not need to be populated with any values (i.e. the placeholder text is visible).
How can we achieve this?
Attempt 1:
In Formik's initialValues
, I tried not defining any values whose form should be empty initially.
<Formik
initialValues={{
itemType: 'any',
}}
...
>
interface Values {
itemType: string;
minPrice?: number;
maxPrice?: number;
}
However, when a user types something into any of these forms, the browser JS console shows the warning:
index.js:1 Warning: A ponent is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the ponent. More info: https://reactjs/link/controlled-ponents at input
Attempt 2:
Tried setting these values to null
in Formik's initialValues
prop,
<Formik
initialValues={{
itemType: 'any',
minPrice: null,
maxPrice: null,
}}
...
but TypeScript throws an error:
Type 'string' is not assignable to type 'never'. TS2322
Type 'string' is not assignable to type 'never'. TS2322
66 | <Formik
67 | initialValues={{
> 68 | itemType: 'any',
| ^
69 | minPrice: null,
The React app does not even start!
Full Code
import { Button, Modal, Form, Row, Col } from 'react-bootstrap';
import { Formik, FormikHelpers } from 'formik';
interface Values {
itemType?: string;
minPrice?: number;
maxPrice?: number;
}
export function FormModal({show, handleClose, updateFilter}: IModal): JSX.Element {
return (
<Modal show={show} onHide={handleClose}>
<Modal.Body>
<Formik
initialValues={{
itemType: 'any',
minPrice: null,
maxPrice: null,
}}
validationSchema={schema}
onSubmit={(
values: Values,
) => {
updateFilter(values);
handleClose();
}}
>
{( {values, errors, touched, handleChange, handleBlur, handleSubmit, isSubmitting, setFieldValue }) => (
<Form id="updateFilterForm" onSubmit={handleSubmit}>
<Form.Group as={Row} controlId="formItemType">
<Form.Label column sm="3">Item Type</Form.Label>
<Col sm="9">
<Select
name="itemType"
options={itemTypeOptions}
onChange={option => setFieldValue("itemType", option!.value)}
onBlur={handleBlur}
values={values.itemType}
/>
</Col>
</Form.Group>
<Form.Group as={Row} controlId="formPrice">
<Form.Label column sm="3">Price Range</Form.Label>
<Col sm="9">
<Form.Row>
<Col>
<Form.Control
type="number"
name="minPrice"
onChange={handleChange}
onBlur={handleBlur}
value={values.minPrice}
placeholder="Min"
/>
</Col>
<Col>
<Form.Control
type="number"
name="maxPrice"
onChange={handleChange}
onBlur={handleBlur}
value={values.maxPrice}
placeholder="Max"
/>
</Col>
</Form.Row>
</Col>
</Form.Group>
</Form>
)}
</Formik>
</Modal.Body>
</Modal>
)
}
Share
Improve this question
asked Feb 13, 2021 at 20:47
NyxynyxNyxynyx
63.8k163 gold badges507 silver badges856 bronze badges
2
- Have you imported the Select ponent? – Anders Grandjean-Thomsen Commented Feb 14, 2021 at 7:03
- @AndersGrandjean-Thomsen Yes, although not shown in the question. – Nyxynyx Commented Feb 14, 2021 at 17:21
1 Answer
Reset to default 2As far as I can see it seems like you haven't defined your interface anywhere.
[ ... ]
const initialValues: Values = {
itemType: 'any',
minPrice: undefined,
maxPrice: undefined,
};
<Formik initialValues={initialValues} {...}>
When working with interfaces remember when setting values to optional? use undefined and not null, if you must define a initial value.
Your app should pass typscript rules now and pile.