0.10.0
Fully backwards compatible. No breaking changes.
🐛 Bug Fixes
- Fix checkbox behavior #223 by
🎉 New Feature
<Field>
now also accepts a render prop.
Before
<Field name="firstName" placeholder="First Name" />
<Field name="firstName" placeholder="First Name" component={MyInput} />
After
<Field name="firstName" placeholder="First Name" /> // same as before
<Field name="firstName" placeholder="First Name" component={MyInput} /> // same as before
<Field
name="firstName"
render={({field, form}) => /* note: props to Field not passed thru, cuz they are available already */
<div>
<input {...field} placeholder="firstName" />
{/* whatever */}
</div>
}
/>
<Field name="firstName">
{({field, form}) =>
<div>
<input {...field} placeholder="firstName" />
{/* whatever */}
</div>}
</Field>
With TypeScript
import * as React from 'react';
import { Formik, FormikProps, Form, Field, FieldProps } from 'formik';
interface MyFormValues {
firstName: string;
}
export const MyApp: React.SFC<{}> = () => {
return (
<div>
<h1>My Example</h1>
<Formik
initialValues={{ firstName: '' }}
onSubmit={(values: MyFormValues) => alert(JSON.stringify(values))}
render={(_formikBag: FormikProps<MyFormValues>) =>
<Form>
<Field
name="firstName"
render={({ field, form }: FieldProps<MyFormValues>) =>
<div>
<input type="text" {...field} placeholder="First Name" />
{form.touched.firstName &&
form.errors.firstName &&
form.errors.firstName}
</div>}
/>
</Form>}
/>
</div>
);
};
Real-world example (composing render functions)
import * as React from 'react';
import * as cx from 'classnames';
import { Field, FieldConfig, FieldProps } from 'formik';
export interface FieldsetProps {
/** blah */
}
// This wraps `<Field render>` with our error/touched logic, display, and formatting.
export const Fieldset: React.SFC<FieldsetProps & FieldConfig> = ({ name, render, ...rest }) =>
<Field
name={name}
render={({ field, form }: FieldProps<MyFormValues>) =>
<div
className={cx('fieldset', {
'fieldset--error': form.errors[name] && form.touched[name],
})}
>
{render({ field, form })}
{form.touched.firstName &&
form.errors.firstName &&
form.errors.firstName}
</div>
}
{...rest}
/>;
import * as React from 'react';
import { Formik, FormikProps, Form, Field, FieldProps } from 'formik';
export interface MyAppProps {}
interface MyFormValues {
firstName: string;
}
export const MyApp: React.SFC<MyAppProps> = () => {
return (
<div>
<h1>My Example</h1>
<Formik
initialValues={{ firstName: '' }}
onSubmit={(values: MyFormValues) => alert(JSON.stringify(values))}
render={({
_formikBag /* values, errors, handleChange ... */,
}: FormikProps<MyFormValues>) =>
<Form>
<Fieldset
name="firstName"
render={({ field }: FieldProps<MyFormValues>) =>
/** Stay DRY, just deal with the input, since errors handled in Fieldset */
<input type="text" {...field} />}
/>
</Form>}
/>
</div>
);
};
Note: In order to maintain backwards compat, the order or precedence among the render functions is DIFFERENT than <Formik />
's.
<Field>
:render
>children
>component
<Formik>
:component
>render
>children
This is because <Field/>
defaults to component="input"