How to change a field in a redux-form?

2020-08-01 07:08发布

问题:

In my react component I am trying to set a field called 'total'. I have imported the change action as a prop into my component:

import React, { Component, Fragment } from 'react'
import { Field, FieldArray, reduxForm, getFormValues, change } from 'redux-form'
import { connect } from 'react-redux'
import { CalcTotal } from './calculationHelper';



const renderField = ({ input, label, type, meta: { touched, error } }) => (
  <div>
    <label>{label}</label>
    <div>
      <input {...input} type={type} placeholder={label} />
      {touched && error && <span>{error}</span>}
    </div>
  </div>
)

const renderMods = ({ fields, meta: { error, submitFailed } }) => (
  <Fragment>
    <ul>
      <li>
        <button type="button" onClick={() => fields.push({})}>
          Add Modification
      </button>
        {submitFailed && error && <span>{error}</span>}
      </li>
      {fields.map((mod, index) => (
        <li key={index}>
          <button
            type="button"
            title="Remove Mod"
            onClick={() => fields.remove(index)}
          />
          <h4>Mod #{index + 1}</h4>
          <Field
            name={`${mod}.lastYear`}
            type="number"
            component={renderField}
            label="Last Year"
          />
          <Field
            name={`${mod}.currentYear`}
            type="number"
            component={renderField}
            label="Current Year"
          />



          <Field name={`${mod}.type`} component="select" label="Type">
            <option />
            <option value="-">Expense</option>
            <option value="+">Income</option>
            <option value="-">Tax</option>
          </Field>


        </li>
      ))}
    </ul>

    <Field
      name="total"
      type="number"
      component="input"
      label="Total modifications"
      text="0"
    />

  </Fragment>
)


class FieldArraysForm extends Component {



  render() {
    const { handleSubmit, formValues, change } = this.props



    if (formValues) {
      console.log('formvalues', formValues);
      const test = CalcTotal(2000);
      console.log('calc=', test);
      debugger
      this.props.change('fieldArraysForm', 'total', 5000)
    }

    return (
      <form onSubmit={handleSubmit}>

        {/* <button onClick={this.changeStuff}>set total</button> */}

        <FieldArray name="mods" component={renderMods} />




        <div>
          <button type="submit" >
            Submit
        </button>

        </div>
      </form>
    )
  }
}



const mapStateToProps = (state) => ({
  formValues: getFormValues('fieldArraysForm')(state),
});

const mapDispatchToProps = {
  change
};


// const Example = reduxForm({
//   form: 'fieldArraysForm', // a unique identifier for this form
// })(FieldArraysForm)

// const ConnectedForm = connect(
//   mapStateToProps,
//   mapDispatchToProps,
// )(Example);

// export default ConnectedForm

export default reduxForm({
  form: "fieldArraysForm"
})(
  connect(
    mapStateToProps,
    mapDispatchToProps
  )(FieldArraysForm)
);

The line where the code fall into an infinite loop:

this.props.change('fieldArraysForm', 'total', 5000)

How /where do I put this statement to make sure the 'total' field is changed and not get into a loop?Which React lifecycle event would suit? I want to fire this whenever there is a form change on any field.

回答1:

You'll need to move your statement out of the render method and into the componentDidUpdate lifecycle method (you also need an if statement to prevent an infinite loop):

componentDidUpdate(prevProps) {
    if (this.props.someValue !== prevProps.someValue) {
      this.props.change("formName", "formField", "newFormValue");
    }
  }

Working example: https://codesandbox.io/s/r5zz36lqnn (selecting the Has Email? radio button populates the email field with test@example.com, unselecting the radio button resets the email field to "")