Home > Mobile >  ReactJS when triggering an event from child component inside map() function, the index is always zer
ReactJS when triggering an event from child component inside map() function, the index is always zer

Time:10-21

I used ASP.NET MVC React template so the parent is a Class component and the child is a function component.

This is an example of the object:

invitation: {
    mainName: "Joe Bloggs",
    mainEmailAddress: "[email protected]",
    invitees: [
      {
        "id": "1",
        "name": "Joe Bloggs",
        "email": "[email protected]",
        "drinking": "",
        "diet": "",
        "rsvp": ""
      },
      {
        "id": "2",
        "name": "John Smith",
        "email": "[email protected]",
        "drinking": "",
        "diet": "",
        "rsvp": ""
      }
    ]
  }

In the Parent component

    this.state.invitation.invitees.map((guest, index) =>{
                          return (<RsvpForm key={guest.id} translations={this.translations} context={context.state} invitee={guest} index={index} handleOnChange={this.updateGuest} />);
  }) : null
                      }

The updateGuest function (in the parent component)

  updateGuest = (e, i) => {

const name = e.target.name;
const value = e.target.value;

this.setState(prevState => {
  return {
    invitation: {
      ...prevState.invitation,
      invitees: [...prevState.invitation.invitees.slice(0, i),
      { ...prevState.invitation.invitees[i], [name]: value },
      ...prevState.invitation.invitees.slice(i   1)]
    }

  }
});

}

And the RSVP form (Child Component). The form has more HTML elements but I am pasting the crucial part

            <div className="mb-2" >
            <label className="form-label">{getTranslation(props.context, 'RSVP')}</label>
            <div className="row" >
                <div className="col-auto">
                    <input type="radio" onChange={(e) => props.handleOnChange(e, props.index)} checked={props.invitee.rsvp == "Yes"} className="btn-check" name="rsvp" id="success-outlined" autoComplete="off" value="Yes" />
                    <label className="btn btn-outline-success" htmlFor="success-outlined">{getTranslation(props.context, 'Yes')}</label>

                </div>
                <div className="col-auto d-none d-sm-block d-md-none" />

                <div className="col-auto">
                    <input type="radio" onChange={(e) => props.handleOnChange(e, props.index)} checked={props.invitee.rsvp == "No"} className="btn-check" name="rsvp" id="danger-outlined" autoComplete="off" value="No" />
                    <label className="btn btn-outline-danger" htmlFor="danger-outlined">No</label>
                </div>
            </div>

        </div>

This renders correctly. I can see two forms one for Joe Bloggs and one for John Smith.

However since the handleOnChange passes the index back to the parent to update the corresponding property of the invitee that was clicked, the index is always 0, not matter which one I click, even though, when rendering I can see 0 and 1 respectively.

Hence when John Smith RSVPs, it actually changes Joe's RSVP.

Can anyone figure out what I am missing here?

CodePudding user response:

You can't have a fixed id in the component especially if it's going to be repeated.

You can modify your code in the child component like below:

id={"success-outline" props.index}

You may change the name of the radio group name as well.

  • Related