With a Formik
context all setup, as well as a Form
we're ready to explore adding input
s so your form can start receiving data. The first method is the Field
component. It has 3 different methods of rendering which we'll cover.
The most basic method is just supplying a name
field. The name
field will link up a specific field value to the path you have supplied. So in the case below we want the Field
to update the firstName
key of our form. The default of Field
is treated as just an input
with type="text"
. So you are able to add all the normal styling and other props to a Field
and it will be applied.
<Formik initialValues={{ firstName: "", }} onSubmit={handleSubmit} > {() => { return ( <Form className="h-screen flex content-center flex-col justify-center"> <Field name="firstName" className="border-2" /> </Form> ); }} </Formik>
Field
also takes a component
prop that if you supply a custom component will forward all the internal field props on to that component. In this case we only care about the field
prop that Field
passes down. This includes things like value=""
and onChange
and onBlur
, etc.
const MySpecialField = ({ field }) => { return <input {...field} className="border-2" />; };
To use the component you pass it in to component
prop. The className
has been moved into the special field but just note that all props you pass to Field
will be passed down as props. However Formik
will override the field
and form
prop as those are internal prop names passed to the component to allow you to control things you need.
<Formik initialValues={{ firstName: "", }} onSubmit={handleSubmit} > {() => { return ( <Form className="h-screen flex content-center flex-col justify-center"> <Field name="firstName" component={MySpecialField} /> </Form> ); }} </Formik>
Finally if you don't want to pass props and need access to data that may be supplied in your render. For example if you are loading data, have other state you need to reference, etc. You can supply a child function. The child function will pass the same props as if you supplied a component
. The only real requirement for basic input
needs is to spread the field
prop onto the input.
<Formik initialValues={{ firstName: "", }} onSubmit={handleSubmit} > {() => { return ( <Form className="h-screen flex content-center flex-col justify-center"> <Field name="firstName"> {({ field }) => { return <input {...field} className="border-2" />; }} </Field> </Form> ); }} </Formik>
Overall pick the version of Field
that works best for your use case. In general I find myself mixing these but reaching for the child as a function as it allows me to grab other data that is available without the need to pass significant amount of props. Also in general I may want a Field
that has no reference to Formik
but merely want to pass along onChange
, onBlur
, and other small bits of info.
All together all the Field
s in conjunction look like this. They will all update, and all render exactly the same.
import React from "react"; import { Formik, Form, Field } from "formik"; const MySpecialField = ({ field }) => { return <input {...field} className="border-2" />; }; function App() { const handleSubmit = (values) => { console.log(values); }; return ( <div className="App"> <Formik initialValues={{ firstName: "", }} onSubmit={handleSubmit} > {() => { return ( <Form className="h-screen flex content-center flex-col justify-center"> <div className="space-x-4 flex content-center justify-center"> <Field name="firstName" className="border-2" /> <Field name="firstName" component={MySpecialField} /> <Field name="firstName"> {({ field }) => { return <input {...field} className="border-2" />; }} </Field> <button type="submit" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" > Submit </button> </div> </Form> ); }} </Formik> </div> ); } export default App;