ReactJS - Formik

Formik is third party React form library. It provides basic form programming and validation. It is based on controlled component and greatly reduces the time to do form programming. Let us recreate the expense form using Formik library.
First, create a new react application, react-formik-app using Create React App or Rollup bundler by following instruction in Creating a React application chapter.
Next, install the Formik library.
cd /go/to/workspace npm install formik --save

Next, open the application in your favorite editor.
Next, create src folder under the root directory of the application.
Next, create components folder under src folder.
Next, create a file, ExpenseForm.css under src folder to style the component.
input[type=text], input[type=number], input[type=date], select {
   width: 100%;
   padding: 12px 20px;
   margin: 8px 0;
   display: inline-block;
   border: 1px solid #ccc;
   border-radius: 4px;
   box-sizing: border-box;
}
input[type=submit] {
   width: 100%;
   background-color: #4CAF50;
   color: white;
   padding: 14px 20px;
   margin: 8px 0;
   border: none;
   border-radius: 4px;
   cursor: pointer;
}
input[type=submit]:hover {
   background-color: #45a049;
}
input:focus {
   border: 1px solid #d9d5e0;
}
#expenseForm div {
   border-radius: 5px;
   background-color: #f2f2f2;
   padding: 20px;
}
#expenseForm span {
   color: red;
}
Next, create a file, ExpenseForm.js under src/components folder and start editing.
Next, import React and Formik library.
import React from 'react'; 
import { Formik } from 'formik';

Next, import ExpenseForm.css file.
import './ExpenseForm.css'

Next, create ExpenseForm class.
class ExpenseForm extends React.Component {        
   constructor(props) { 
      super(props); 
   } 
}

Next, set initial values of the expense item in the constructor.
this.initialValues = { name: '', amount: '', date: '', category: '' }

Next, create a validation method. Formik will send the current values entered by the user.
validate = (values) => {
   const errors = {};
   if (!values.name) {
      errors.name = 'Required';
   }
   if (!values.amount) {
      errors.amount = 'Required';
   }
   if (!values.date) {
      errors.date = 'Required';
   }
   if (!values.category) {
      errors.category = 'Required';
   }
   return errors;
}
Next, create a method to submit the form. Formik will send the current values entered by the user.
handleSubmit = (values, setSubmitting) => {
   setTimeout(() => {
      alert(JSON.stringify(values, null, 2));
      setSubmitting(false);
   }, 400);
}
Next, create render() method. Use handleChange, handleBlur and handleSubmit method provided by Formik as input elements event handler.
render() {
   return (
      <div id="expenseForm">
         <Formik
            initialValues={this.initialValues}
            validate={values => this.validate(values)}
            onSubmit={(values, { setSubmitting }) => this.handleSubmit(values, setSubmitting)} >
            {
               ({
                  values,
                  errors,
                  touched,
                  handleChange,
                  handleBlur,
                  handleSubmit,
                  isSubmitting,
                  /* and other goodies */
               }) 
               => (
                  <form onSubmit={handleSubmit}>
                     <label for="name">Title <span>{errors.name && touched.name && errors.name}</span></label>
                     <input type="text" id="name" name="name" placeholder="Enter expense title"
                        onChange={handleChange}
                        onBlur={handleBlur}
                        value={values.name} />

                     <label for="amount">Amount <span>{errors.amount && touched.amount && errors.amount}</span></label>
                     <input type="number" id="amount" name="amount" placeholder="Enter expense amount"
                        onChange={handleChange}
                        onBlur={handleBlur}
                        value={values.amount} />

                     <label for="date">Spend Date <span>{errors.date && touched.date && errors.date}</span></label>
                     <input type="date" id="date" name="date" placeholder="Enter date"
                        onChange={handleChange}
                        onBlur={handleBlur}
                        value={values.date} />

                     <label for="category">Category <span>{errors.category && touched.category && errors.category}</span></label>
                     <select id="category" name="category"
                        onChange={handleChange}
                        onBlur={handleBlur}
                        value={values.category}>
                        <option value="">Select</option>
                        <option value="Food">Food</option>
                        <option value="Entertainment">Entertainment</option>
                        <option value="Academic">Academic</option>
                     </select>

                     <input type="submit" value="Submit" disabled={isSubmitting} />
                  </form>
               )
            }
         </Formik>
      </div>
   )
}
Finally, export the component.
export default ExpenseForm

The complete code of the ExpenseForm component is given below.
import React from 'react';
import './ExpenseForm.css'
import { Formik } from 'formik';

class ExpenseFormik extends React.Component {
   constructor(props) {
      super(props);

      this.initialValues = { name: '', amount: '', date: '', category: '' }
   }
   validate = (values) => {
      const errors = {};
      if (!values.name) {
         errors.name = 'Required';
      }
      if (!values.amount) {
         errors.amount = 'Required';
      }
      if (!values.date) {
         errors.date = 'Required';
      }
      if (!values.category) {
         errors.category = 'Required';
      }
      return errors;
   }
   handleSubmit = (values, setSubmitting) => {
      setTimeout(() => {
         alert(JSON.stringify(values, null, 2));
         setSubmitting(false);
      }, 400);
   }
   render() {
      return (
         <div id="expenseForm">
            <Formik
               initialValues={this.initialValues}
               validate={values => this.validate(values)}
               onSubmit={(values, { setSubmitting }) => this.handleSubmit(values, setSubmitting)} > 
               {
                  ({
                     values,
                     errors,
                     touched,
                     handleChange,
                     handleBlur,
                     handleSubmit,
                     isSubmitting,
                     /* and other goodies */
                  }) => 
                  (
                     <form onSubmit={handleSubmit}>
                        <label for="name">Title <span>{errors.name && touched.name && errors.name}</span></label>
                        <input type="text" id="name" name="name" placeholder="Enter expense title"
                           onChange={handleChange}
                           onBlur={handleBlur}
                           value={values.name} />

                        <label for="amount">Amount <span>{errors.amount && touched.amount && errors.amount}</span></label>
                        <input type="number" id="amount" name="amount" placeholder="Enter expense amount"
                           onChange={handleChange}
                           onBlur={handleBlur}
                           value={values.amount} />

                        <label for="date">Spend Date <span>{errors.date && touched.date && errors.date}</span></label>
                        <input type="date" id="date" name="date" placeholder="Enter date"
                           onChange={handleChange}
                           onBlur={handleBlur}
                           value={values.date} />

                        <label for="category">Category <span>{errors.category && touched.category && errors.category}</span></label>
                        <select id="category" name="category"
                           onChange={handleChange}
                           onBlur={handleBlur}
                           value={values.category}>
                           <option value="">Select</option>
                           <option value="Food">Food</option>
                           <option value="Entertainment">Entertainment</option>
                           <option value="Academic">Academic</option>
                        </select>

                        <input type="submit" value="Submit" disabled={isSubmitting} />
                     </form>
                  )
               }
            </Formik>
         </div>
      )
   }
}
export default ExpenseForm;
Next, create a file, index.js under the src folder and use ExpenseForm component.
import React from 'react';
import ReactDOM from 'react-dom';
import ExpenseForm from './components/ExpenseForm'

ReactDOM.render(
   <React.StrictMode>
      <ExpenseForm />
   </React.StrictMode>,
   document.getElementById('root')
);
Finally, create a public folder under the root folder and create index.html file.
<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8">
      <title>React App</title>
   </head>
   <body>
      <div id="root"></div>
      <script type="text/JavaScript" src="./index.js"></script>
   </body>
</html>
Next, serve the application using npm command.
npm start

Next, open the browser and enter http://localhost:3000 in the address bar and press enter.
Finally, enter a sample expense detail and click submit. The submitted data will be collected and showed in a popup message box.
The interactive version of the form is as follows −

    20 Lectures 
     1.5 hours 

 Anadi Sharma

    60 Lectures 
     4.5 hours 

 Skillbakerystudios

    165 Lectures 
     13 hours 

 Paul Carlo Tordecilla

    63 Lectures 
     9.5 hours 

 TELCOMA Global

    17 Lectures 
     2 hours 

 Mohd Raqif Warsi
 Print
 Add Notes
 Bookmark this page