Brachamul
Brachamul

Reputation: 1974

Dynamically set form field values in React + Redux

My app's store has a store.authState subtree. In this subtree, there are three things, an authToken, an isFetching boolean and, most importantly a fields object. My form contains two fields : username and password.

I have created an action called SET_FORM_FIELD_VALUE which should generate and update each field's state as they are changed by the user.

I would like my SET_FORM_FIELD_VALUE to update the fields object. If a user normally fills in both username and password fields, my store.authState should look like this:

{
    authToken: undefined,
    isFetching: false,
    fields: {
        username: "Brachamul",
        password: "azerty123"
    }
}

However, it seems that my current code actually just overwrites everything and I end up with :

{
    field: {
        username: "Brachamul"
    }
}

The data in the field changes based on what field I last edited. It's either username or password.

Here is my code :

switch (action.type) {
    case 'SET_FORM_FIELD_VALUE':
        let field = {} // create a "field" object that will represent the current field
        field[action.fieldName] = action.fieldValue // give it the name and value of the current field
        return { ...state.fields, field }

How can I change it to fix my issue ?

Upvotes: 1

Views: 3080

Answers (2)

CDM
CDM

Reputation: 517

i used change() from 'redux-form'

which only re rendered that specific form input, and isued it pretty often. everytime the user clicked a dropdown menu it suggested values in 2 input fields

i abstracted away the html from the anwser and some other stuff.


import { FieldArray, Field, change, reduxForm } from 'redux-form';


class WizardFormThirdPage extends react.component{

runInject(target,value){
    target.value= value; // sets the client html to the value
    // change (formName, Fieldname, Value) in the state
    this.props.dispatch(change('spray-record', target.name, value))
  }

injectFormvalues(){

      var tr = div.querySelector(".applicator-equipment");
      var name = div.querySelector("select").value;
      if(!name.includes("Select Employee")){
        // var inputs = tr.querySelectorAll("input");

        var employeeDoc= findApplicatorByName(name); // synchronous call to get info
        tractor = tr.querySelector("input")
        sprayer = tr.querySelectorAll("input")[1];
        // here i send off the change attribute
        this.runInject(tractor,Number(employeeDoc.default_t))
        this.runInject(sprayer,Number(employeeDoc.default_s));
}

}


// you have to connect it get the dispatch event.
export default connect(state => ({
  enableReinitialize: true,
}))(reduxForm({
  form: "myFormName", //                 <------ same form name
  destroyOnUnmount: false, //        <------ preserve form dataLabel
  forceUnregisterOnUnmount: true, // <------ unregister fields on unmount
  validate,
})(WizardFormThirdPage));

Upvotes: 0

QoP
QoP

Reputation: 28397

Your return is wrong, it should be something like this

switch (action.type) {
    case 'SET_FORM_FIELD_VALUE':
             return {
                   ...state,
                   fields: {
                         ...state.fields,
                         [action.fieldName] : action.fieldValue
                   }
             }
}

Hope it helps.

Upvotes: 3

Related Questions