2

I'm storing default values of multiple radioGroups in an State array object in react. Current state object formRating has about 22 elements where in each is radioGroup's defaulValue is stored

Once stored into the state, the array object looks like below;

formRating: Array[1]
  0: Array[22]
   0:{…} 
      condId: "C2.1(a)" 
      rate: "3"
   1:{…}
   2:{…}
  .... goes till 21:{...}

Upon the user selecting a different value on the radioGroup, i want that to be updated in the state array.

For example say user selected the radio button of value 2 of the radioGroup with the name or ID "C2.1(a)", I want the onChange method to update the state as follows. (just the rate of the element with matching condId changes while rest remains the same.)

formRating: Array[1]
  0: Array[22]
   0:{…} 
      condId: "C2.1(a)" 
      rate: "2"
   1:{…}
   2:{…}
  .... goes till 21:{...}

Ive tried the following onChange method.

onChange={this.changeButton('C2.1(a)')}

changeButton = (condId)=> e =>{
e.preventDefault();
this.props.handleChangeRadio(condId);
  }

handleChangeRadio =(condId) => e =>{
  console.log(e, condId);
  this.setState(prevState => ({

  formRating: prevState.formRating.map(
    el => el.condId === [condId]? { ...el, rate: e.target.value }: el
  )
 }))
}

Currently I am using a button to initiate the state array object formRating.

in the render

const formValues= [{condId :'C2.1(a)',rate:'3'},
             {condId :'C2.2(b)',rate:'3'},
             {condId :'C2.2(a)',rate:'3'},
             {condId :'NTS1.1(a)',rate:'3'},
             {condId :'C2.3(a)',rate:'3'}]; //22 such items in the array

and in the form

<RaisedButton label="Select Default Values" secondary={true} onClick={this.defaultButton(formValues)} style={{width:300}}/>


defaultButton =(formValues)=> e => {
    e.preventDefault();
    this.props.setRadio(formValues);
   }


   setRadio= (formValues) => {
 const {formRating} = this.state;
 this.setState({
   formRating: [formValues]})
  }

Any help is appreciated

Dworo
  • 153
  • 1
  • 4
  • 15

3 Answers3

2

If I understand correctly, the only change that should be nessisary is to remove the [ and ] from around the [condId] in your map() callback function.

By doing that, the equality test in your mapping logic will correctly match array items in the fromRating array against the supplied condId argument:

handleChangeRadio =(condId) => e =>{
  console.log(e, condId);
  this.setState(prevState => ({

  formRating: prevState.formRating.map(
       /* Remove [ and ] */
    el => el.condId === condId ? { ...el, rate: e.target.value } : el
  )
 }))
}
Dacre Denny
  • 29,664
  • 5
  • 45
  • 65
  • thanks for the answer I've tried this but the state still remains the same :( – Dworo Aug 02 '19 at 06:49
  • it all came down to the [ ] mate. Thanks! – Dworo Aug 02 '19 at 07:13
  • While we are in the same context, what would be the best method to set the defaultValue of the radioGroup from the state array object against the condId? – Dworo Aug 02 '19 at 07:59
0

You need to directly pass value to handleChangeRadio function, because e is a synthetic event and once the function get executed e is nullified and you cannot access further.

changeButton = (condId)=> e =>{
    e.preventDefault();
    this.props.handleChangeRadio(condId,e.target.value);
}

So your handleChangeRadio function should be,

handleChangeRadio =(condId,newRate) =>{
  this.setState(prevState => ({
  formRating: prevState.formRating.map(
    el => el.condId === condId ? { ...el, rate: newRate }: el
  )
 }))
}

Also make sure to remove [ and ] from condId which is supposed to create an object and your condition will always be false.

Demo

ravibagul91
  • 20,072
  • 5
  • 36
  • 59
  • Thanks I tried this just now but the state still remains the same. – Dworo Aug 02 '19 at 06:50
  • Post stringified version of `formRating`. I think you have array of array. – ravibagul91 Aug 02 '19 at 06:56
  • Sorry Im a total newbie to react. How can i fix this? – Dworo Aug 02 '19 at 06:57
  • Just do `console.log(JSON.stringify(this.state.formRating))` in render method and post here. – ravibagul91 Aug 02 '19 at 06:58
  • You are again doing this wrong `formRating: [formValues]` remove `[` and `]`. – ravibagul91 Aug 02 '19 at 07:05
  • 1
    Thanks I think i fixed it :D Had [ ] around formRating in setRadio method which creates an array of an array like you said. Like all the answers mentioned my improper use of [ ] was the culprit. Thanks! – Dworo Aug 02 '19 at 07:06
  • 1
    Yes. @ravibagul91 youre absolutely right aha. Thanks heaps! – Dworo Aug 02 '19 at 07:13
  • While we are in the same context, what would be the best method to set the defaultValue of the radioGroup from the state array object against the condId? – Dworo Aug 02 '19 at 08:00
0

As pointed out by both @ravibagul91 and @denny removing [ ] around formValues from setRadio method and changing passing the values as pointed out by @ravibagul91 worked! For anyone else wondering it looks like this now and it works.

  componentDidMount(){
   this.props.setRadio(formValues);
   }

  setRadio= (formValues) => {
    const {formRating} = this.state;
    this.setState({
    formRating: formValues})
    }

   onChange={this.changeButton('C2.1(a)')}

   changeButton = (condId)=> e =>{
    e.preventDefault();
    this.props.handleChangeRadio(condId,e.target.value);


     }

handleChangeRadio =(condId,newRate) =>{
  this.setState(prevState => ({

formRating: prevState.formRating.map(
  el => el.condId === condId? { ...el, rate: newRate }: el
     )


   }))

}
Dworo
  • 153
  • 1
  • 4
  • 15