Formik Components
Formik provides a few Components to be used that will save us more time, reduce code duplication, and make the code more consistent and organized.
Login Form With Formik Components
- Import
Formik
,Form
,Field
andErrorMessage
fromformik
. - Wrap and return the entire form inside
<Formik>
Component withformik
as a parameter. - Add
initialValues
,onSubmit
andvalidationSchema
as Props to<Formik>
Component. - Replace the native
<form>
element with the<Form>
Component. - Wrap and return the
label
,input
, and thevalidation div message
inside<Field>
withformikField
as a parameter. - Add the
name
attribute to the<Field>
component instead of the<input>
element. - spread
{...formikField.field}
inside the<input>
element. - Wrap and return the
validation div
inside<ErrorMessage>
component withErrMessage
as a parameter and add thename
attribute to it. - log
formikField
inside a<pre>
to see the entireformikField
object.
import React from "react";
import { Formik, Form, Field, ErrorMessage } from "formik";
import * as yup from "yup";
/**
* LoginFormikComponents Component
*/
const LoginFormikComponents = () => {
const initialValues = {
email: "",
password: "",
rememberMe: false,
};
const onSubmit = (values) => console.log(JSON.stringify(values, null, 4));
const validationSchema = yup.object({
email: yup
.string()
.email("Please enter a valid email address")
.required("Email field is required"),
password: yup.string().required("Password field is required"),
});
return (
<Formik
initialValues={initialValues}
onSubmit={onSubmit}
validationSchema={validationSchema}
>
{(formik) => {
return (
<Form>
<div style={{ padding: 20 }}>
<Field name="email">
{(formikField) => {
return (
<>
<label htmlFor="email" style={{ display: "block" }}>
email
</label>
<input type="email" id="email" {...formikField.field} />
<ErrorMessage name="email">
{(errMessage) => {
return (
<div style={{ color: "red" }}>{errMessage}</div>
);
}}
</ErrorMessage>
<pre>{JSON.stringify(formikField, null, 4)}</pre>
</>
);
}}
</Field>
<Field name="password">
{(formikField) => {
return (
<>
<label htmlFor="password" style={{ display: "block" }}>
password
</label>
<input
type="password"
id="password"
{...formikField.field}
/>
<ErrorMessage name="password">
{(errMessage) => {
return (
<div style={{ color: "red" }}>{errMessage}</div>
);
}}
</ErrorMessage>
<pre>{JSON.stringify(formikField, null, 4)}</pre>
</>
);
}}
</Field>
<Field name="rememberMe">
{(formikField) => {
return (
<>
<label htmlFor="rememberMe" style={{ display: "block" }}>
remember me
</label>
<input
type="checkbox"
id="rememberMe"
defaultChecked={formikField.field.value}
{...formikField.field}
/>
<pre>{JSON.stringify(formikField, null, 4)}</pre>
</>
);
}}
</Field>
<button style={{ display: "block" }}>submit</button>
</div>
<pre>{JSON.stringify(formik, null, 4)}</pre>
</Form>
);
}}
</Formik>
);
};
export default LoginFormikComponents;
Formik Reusable Components
As we can see inside each <Field>
component there are
<label>
<input>
<ErrorMessage>
So, it's a good chance to create a Reusable Component that includes all of that.
FormikErrorMessage.jsx
import React from "react";
import { ErrorMessage } from "formik";
/**
* FormikErrorMessage Component
*/
const FormikErrorMessage = ({ name }) => {
return (
<ErrorMessage name={name}>
{(errMessage) => {
return <div style={{ color: "red" }}>{errMessage}</div>;
}}
</ErrorMessage>
);
};
export default FormikErrorMessage;
FormikField.jsx
import React from "react";
import { Field } from "formik";
import FormikErrorMessage from "./FormikErrorMessage";
/**
* FormikField Component
*/
const FormikField = ({ name, type, label }) => {
return (
<Field name={name}>
{(formikField) => {
return (
<>
<label htmlFor={name} style={{ display: "block" }}>
{label}
</label>
<input
type={type}
id={name}
{...formikField.field}
defaultChecked={formikField.field.value}
/>
<FormikErrorMessage name={name} />
<pre>{JSON.stringify(formikField, null, 4)}</pre>
</>
);
}}
</Field>
);
};
export default FormikField;
And here is the final code after using the reusable components.
LoginFormikComponentsShared.jsx
import React from "react";
import { Formik, Form } from "formik";
import * as yup from "yup";
import FormikField from "./shared/FormikField";
/**
* LoginFormikComponents Component
*/
const LoginFormikComponents = () => {
const initialValues = {
email: "",
password: "",
rememberMe: false,
};
const onSubmit = (values) => console.log(JSON.stringify(values, null, 4));
const validationSchema = yup.object({
email: yup
.string()
.email("Please enter a valid email address")
.required("Email field is required"),
password: yup.string().required("Password field is required"),
});
return (
<Formik
initialValues={initialValues}
onSubmit={onSubmit}
validationSchema={validationSchema}
>
{(formik) => {
return (
<Form>
<div style={{ padding: 20 }}>
<FormikField label="Email" name="email" type="email" />
<FormikField label="Password" name="password" type="password" />
<FormikField
label="Remember Me"
name="rememberMe"
type="checkbox"
/>
<button style={{ display: "block" }}>submit</button>
</div>
<pre>{JSON.stringify(formik, null, 4)}</pre>
</Form>
);
}}
</Formik>
);
};
export default LoginFormikComponents;
Top comments (0)