How to calculate total and subtotal in redux-form using formValueSelector

人走茶凉 提交于 2021-01-29 09:24:53

问题


I want to calculate total and subtotal using a field array like input date.

This is my renderDetail Component:

     renderDetail = ({fields, meta: { error,submitFailed}}) => (
               <dl>
                  <dt>
                    <button type="button" className= 'btn btn-primary' onClick={() => 
                      fields.push()}>Add Detail</button>
                     {submitFailed && error && <span>{error}</span>}
                     </dt>
                    { fields.map((detailRegister, index) =>

                   <dd key={index}>
                      <br></br>
                        <button className= 'btn btn-light mr-2'
                         type="button"
                         title="Remove detail"
                         onClick={() => { fields.remove(index)
                           if(fields.length == 0 || fields.length === undefined){

                            }
                           try{
                           for(let x in fields){
                              fields.remove(index) 
                              let d = fields.selectedIndex;
                               if(fields.remove(index) && d >= 1 && d< fields.length ){
                                 fields.removeAll(index);
                              }
                            }
                         }catch{console.info("deletes non numeric index")}

                             }}> Delete </button>

                   <h4>DetailRegister #{index + 1}</h4>

                 <Field 
                    id={`${detailRegister}._id`}
                    name={`${detailRegister}.quantity`}
                    component= {NumberPickerInteger}
                    placeholder= '...quantity'
                    label = "Quantity" 
                     />
                     <br></br>
                       <h3><b>Product</b></h3>
                           <Field 
                            id={`${registerDetail}._id`}
                            name={`${registerDetail}.product.code`}
                            type="number"
                            component= {RenderFieldNumeric}
                            placeholder='...product's code'
                            label = "Product's code" 
                             />
                 <Field 
                   id={`${registerDetail}._id`}
                   name={`${registerDetail}.product.name`}
                   type="text"
                   component= {RenderField}
                   placeholder='...product's name'
                   label = "Product's name" 
                   />
                 <Field 
                   id={`${registerDetail}._id`}
                   name={`${registerDetail}.product.price`}
                   component= {NumberPickerr}
                   placeholder= '...Price'
                   label = "product's price" 
                   />
                 <br></br>
                  <h3><b>Subtotal</b></h3>
                  <Field 
                  id={`${registerDetail}._id`}
                  name={`${registerDetail}.subtotal`}
                  component= {SubtotalWidget}
                  placeholder= '...subtotal'
                  label = "Subtotal" 
                />

                     </dd>
                      )
                        }

                      {error && <dt className="error">{error}</dt>}
                      </dl> 
                   );

These are the formulas to calculate subtotal and total:

      const calculatedSubtotal = (detail) =>{

         detail = [];

         const subtotals = [];

          detail.map((detailItem,index) =>{

             subtotals[index] = detailItem[index].quantity * detailItem[index].product.price;

            return subtotals[index];

               })

             } 

      const calculatedTotal = (detail) =>{

         detail = [];

          let total = 0;

           const subtotals = [];


            detail.map((detailItem,index) =>{
               subtotals[index] = detailItem[index].quantity * detailItem[index].product.price;

             total += subtotals[index];
             })

          return total;
      }

These are my lifecycle components willReceiveProps, componentDidUpdate and shouldComponentUpdate from BillForm class component:

      componentWillReceiveProps = nextProps => {
           // Load Contact Asynchronously
            const { bill } = nextProps;
            const { change, detail } = nextProps;
                 if (bill._id !== this.props.bill._id) {
                    // Initialize form only once
                     this.props.initialize(bill);
                     this.isUpdating = true;
                     }
                 if(this.props.renderDetail !== nextProps.renderDetail){
                change(`detail[${this.props.index}].subtotal`,calculatedSubtotal(detail));
                  change('total',calculatedTotal(detail));
               }

            };

            componentDidUpdate(prevProps,prevState,snapShot){

              const {change} = prevProps;

              const {detail} = prevProps;

              if(this.props.detail !== prevProps.detail){
                  change(`detail[${this.props.index}].subtotal`,calculatedSubtotal(detail));
                  change('total',calculatedTotal(detail));
                  }
            }

              shouldComponentUpdate(nextProps, nextState) {
                 return this.props.detail !== nextProps.detail
                } 

This is my render when I getting components in form:

                 render(){

                   const { handleSubmit, loading,submitting, pristine, reset} = this.props;

                 if (loading) {
                    return <span>Loading...</span>;
                  }

                return (
               <form onSubmit={handleSubmit}>

              <div>Detail:</div>

                      <FieldArray
                        name='detail'
                        component={this.renderDetail}
                        label='Detail'
                       />

                     <Field
                      name='total'
                      component={TotalWidget}
                      placeholder= '...total'
                      label='Total'
                        />


                    <Link className='btn btn-light mr-2' to='/bills'>
                        Cancel
                         </Link>
                         <button className='btn btn-primary mr-2' type='submit'>
                           {this.isUpdating ? 'Update' : 'Create'}
                        </button>
                      </form>
                      );
                  }
                }

And here I'm using formValueSelector to change state and getting total and subtotal using fieldArray called "detail":

          const valueSelector = formValueSelector('bill');


          const makeStateToProps = () =>{

             const mapStateToProps = (state,props) =>{

                    return {

                     detail: valueSelector(state, 
                  `detail[${props.index}].quantity`,`detail[${props.index}].product.price`,
                   `detail[${props.index}].subtotal`
                   )

                }

                   }

                  return mapStateToProps;
               }

Connecting makeStateToProps to reduxForm:

       BillForm = reduxForm(
              {
              form: 'bill',
              enableReinitialize: false,
              validate: validations
              },
              makeMapStateToProps
              )(BillForm)

               const mapDispatchToProps = undefined;

                BillForm = connect(makeMapStateToProps,mapDispatchToProps)(BillForm);

I want calculate Subtotal and total accessing specifies fields from fieldArray using generic specify index.

I run code but changes are not reflected. I can't see subtotal and total calculated from detail.quantity, detail.product.price and detail.subtotal, respectively.

What is wrong?, I need to solve this.

I need you do a working demo for this case.

来源:https://stackoverflow.com/questions/60230808/how-to-calculate-total-and-subtotal-in-redux-form-using-formvalueselector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!