With a Formik context all setup, as well as a Form we're ready to explore adding inputs 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 Fields 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;