Resources:
- Formik tutorial
- useField Formik hook with Typescript
- Using Chakra UI with Formik
- Prop 'id' did not match problem
foreword
Hello everyone.
I will be using create next-app throughout the post but everything in here is appliable to regular React (CRA) applications.
I expect you to be familiar with Chakra UI and Formik
Let's get started =)
Let's start with creating a new NextJS app:
yarn create next-app MyNextApp --typescript
Open created folder in your IDE, then install Formik and Chakra UI
yarn add @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^4 formik
Next we create a new folder components and a file named CustomInput.tsx
Inside that file create a new Functional component named CustomInput:
export const CustomInput: FC = ({ label, ...props }) => {
const [field, meta] = useField(props);
return (
<FormControl isInvalid={meta.touched && !!meta.error}>
<FormLabel>
{label}
</FormLabel>
<Input {...field} />
</FormControl>
);
}
At this moment Typescript will yell at us saying it doesn't know what're the label and props, we need to explain to that silly what those things are. So we need an interface which can be written two ways: either by extending JSX.IntrinsicElements['input'] interface or by intersecting FieldHookConfig<string> type:
// intersecting
interface ICustomFieldProps {
label: string;
}
// FieldHookConfig accepts value type as an argument,
// it is 'string' for input elements
export const CustomInput: FC<FieldHookConfig<string> & ICustomFieldProps> = ({
label,
...props
}) => {
...
}
// extending
interface ICustomFieldProps extends JSX.IntrinsicElements['input'] {
label: string;
name: string;
}
export const CustomInput: FC<ICustomFieldProps> = ({ label, ...props }) => {
...
}
Choose whatever way you like.
Now let's create our form. Open pages/index.tsx file, delete everything in between div and replace div with Formik component.
Add some dummy initialValue and onSubmit to Formik component, place <Form> and <CustomInput /> inside <Formik>:
const Home: NextPage = () => {
return (
<Formik initialValues={{name:''}} onSubmit={(val) => alert(val.name)}>
<Form>
<CustomInput name='name' label='name' />
<Button type='submit'>Submit</Button>
</Form>
</Formik>
)
}
export default Home
Ta-da. We now have a form built with Chakra UI and managed by Formik.
But. If you're using NextJS and you open devtools console, you will see a big fat error:
Warning: Prop `id` did not match.
We can fix this by adding id to our form elements explicitly. Inside CustomInput.tsx add id attribute to Input and FormLabel components and htmlFor attribute to FormLabel:
export const CustomInput: FC<IFormikFieldProps & FieldHookConfig<string>> = ({
label,
...props
}) => {
const [field, meta] = useField(props);
return (
<FormControl isInvalid={meta.touched && !!meta.error}>
<FormLabel
id={`${props.id}-${props.name}-label`}
htmlFor={`${props.id}-${props.name}-input`}
>
{label}
</FormLabel>
<Input
{...field}
id={`${props.id}-${props.name}-input`}
/>
</FormControl>
);
};
Cool. It's done.
notes:
- for select, you must pass
props.childrento Chakra UI'sSelectcomponent explicitly:
<Select {...field} id={`${props.id}-${props.name}-select`}>
{props.children}
</Select>
- you can add
FormErrorMessagecomponent, too
Thanks for reading =)
Top comments (0)