ReactJS - Add Expense



Open ExpenseEntryItemList.js and import connect from redux library.

import { connect } from 'react-redux';

Next, import Formik library..

iimport { Formik } from 'formik';

Next, import withRouter method from router library.

import { withRouter } from "react-router-dom";

Next, import addExpense from our action library.

import { addExpense } from '../actions/expenseActions';

Next, create constructor with initial values for expenses.

constructor(props) {
   super(props); 
   this.initialValues = { name: '', amount: '', spend_date: '', category: '' } 
}

Next, write the validate method.

validate = (values) => {
   const errors = {};
   if (!values.name) {
      errors.name = 'Required';
   }
   if (!values.amount) {
      errors.amount = 'Required';
   }
   if (!values.spend_date) {
      errors.spend_date = 'Required';
   }
   if (!values.category) {
      errors.category = 'Required';
   }
   return errors;
}

Next, add event handler method.

handleSubmit = (values, setSubmitting) =< {
   setTimeout(() =< {
      let newItem = {
         name: values.name,
         amount: values.amount,
         spendDate: values.spend_date,
         category: values.category
      }
      this.props.addExpense(newItem);
      setSubmitting(false);
      this.props.history.push("/list");
   }, 400);
}

Here,

  • Used addExpense method to add expense item
  • Use router history method to move to expense list page.

Next, update render method with form created using Formik library.

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="spend_date">Spend Date <span>{errors.spend_date && touched.spend_date && errors.spend_date}</span></label>
                     <input type="date" id="spend_date" name="spend_date" placeholder="Enter date"
                        onChange={handleChange}
                        onBlur={handleBlur}
                        value={values.spend_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>
   )
}

Next, map dispatch method to component properties.

const mapDispatchToProps = { 
   addExpense, 
};

Finally, connect the component to store and also wrap the component with WithRouter to get programmatic access to router links.

export default withRouter(connect(
   null,
   mapDispatchToProps
)(ExpenseEntryItemForm));

The complete source code of the component is as follows −

import React from "react";

import { connect } from 'react-redux';
import { Formik } from 'formik';
import { withRouter } from "react-router-dom";
import { addExpense } from '../actions/expenseActions';

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

      this.initialValues = { name: '', amount: '', spend_date: '', category: '' }
   }
   validate = (values) => {
      const errors = {};
      if (!values.name) {
         errors.name = 'Required';
      }
      if (!values.amount) {
         errors.amount = 'Required';
      }
      if (!values.spend_date) {
         errors.spend_date = 'Required';
      }
      if (!values.category) {
         errors.category = 'Required';
      }
      return errors;
   }
   handleSubmit = (values, setSubmitting) => {
      setTimeout(() => {
         let newItem = {
            name: values.name,
            amount: values.amount,
            spendDate: values.spend_date,
            category: values.category
         }
         this.props.addExpense(newItem);
         setSubmitting(false);
         this.props.history.push("/list");
      }, 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="spend_date">Spend Date <span>{errors.spend_date && touched.spend_date && errors.spend_date}</span></label>
                        <input type="date" id="spend_date" name="spend_date" placeholder="Enter date"
                           onChange={handleChange}
                           onBlur={handleBlur}
                           value={values.spend_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>
      )
   }
}
const mapDispatchToProps = {
   addExpense,
};
export default withRouter(connect(
   null,
   mapDispatchToProps
)(ExpenseEntryItemForm));

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.

List Expenses

Finally, we have successfully created a simple react application with basic features.

Conclusion

React is one of the most popular and highly recommended UI frameworks. True to its popularity, it is being developed for a very long time and actively maintained. Learning react framework is a good starting point for the front end developers and will surely help them to improve their professional career.

reactjs_example.htm
Advertisements