2
votes

I am trying to add react-modal to the items of the mapped array. When I click on the onClick event on the mapped items it opens all the modals at once. What I want is top open selected modal at a time.

Here I am mapping through the employee's array and adding a button to each of them with onClick modal.

const employeeInfo = this.props.employees.map(employee => (
      <tr key={employee.employeeId} className="employee_heading">
        <td>{employee.name}</td>

        <td className="actions">
          <div className="group">
            <button className="edit" onClick={this.toggleEditEmployeeModal}>
              <i className="fas fa-pencil-alt" />
            </button>
            
            //This is the modal component
            <Modal
              open={this.state.openEditEmployeeModal}
              onClose={this.toggleEditEmployeeModal}
              center
            >
              <EditEmployeeModal />
            </Modal>

          </div>
        </td>
      </tr>
    ));
return (
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Employee Id</th>
            <th>Job Title</th>
            <th>Date Of Joining</th>
            <th>Employee Info</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody>{employeeInfo}</tbody>
      </table>
    );
  }

here is the state for toggling the model

state = {
  openEditEmployeeModal: false
};

toggleEditEmployeeModal = () => {
  this.setState({
    openEditEmployeeModal: !this.state.openEditEmployeeModal
  });
};

Now If I click the button it will open all the modal but I want to open a selected modal only. Any help will be appreciated.

2
first of all, really odd way to define your component. but regardless they all open up because they are all looking at the same state variable... I would suggest you do the more common thing and set every employee in its own component and use a HOC to define the dialog open event. or define a single dialog at the parent level which will toggle with the selected employee detailsJony-Y
I updated the post with more code.MontyGoldy
that still wouldnt help. since they are all in the same component and there is only one state flag. what I suggest is that you define each employee in an EmployeeInfo component, there you can do one of two things. define the modal there and set an internal state or define a cb that the parent will know to load the modal but with the employee details.Jony-Y
thank you for your response. Going to try your solutionMontyGoldy
@Jony-Y thanks man its working now as per your instructions.MontyGoldy

2 Answers

2
votes

Three ways:

  1. Render a map of "Employee" components with they own states so the modal is proper to each employee.
  2. Render your current map with modal on the parent component and, from an employee click, set the modal state with that employee context.
  3. Have a key based state with each employee index as a key (state[employeeId]) so you can mutate each separately.
1
votes

I usually separate them into components

const employeeInfo = this.props.employees.map(employee => (
    <Employee employee=employee />
    ));

class Employee extends PureComponent {
   render(){
      constructor(props){
      super(props);
      this.state={visible:false}
     }
 toggleEditEmployeeModal(){
   this.setState({
   visible = !this.state.visible
      })
   }
  var employee = this.props.employee

    return(
      <tr key={employee.employeeId} className="employee_heading">
        <td>{employee.name}</td>

        <td className="actions">
          <div className="group">
            <button className="edit" onClick={this.toggleEditEmployeeModal}>
              <i className="fas fa-pencil-alt" />
            </button>

            //This is the modal component
            <Modal
              open={this.state.visible}
              onClose={this.toggleEditEmployeeModal}
              center
            >
              <EditEmployeeModal />
            </Modal>

          </div>
        </td>
      </tr>
)
    }

}

let me know if you have further problems