Button element in array with onClick property to change state the specific button that is clicked

Viewed 146

I have an array of button that is rendered using .map to print out the rows in data table. Each row have button that trigger the Edit panel popup. The problem that I currently have is when one button is clicked, the Edit panel on all rows.

The code:

          const [showEdit, setShowEdit] = useState([]);

          <tbody>
            {appSettingsList.map((appSettings, i) => (
              <tr key={i}>
                <td>{appSettings.Name}</td>
                <td>{appSettings.BackgroundColor}</td>
                <td>{appSettings.FontSize}</td>
                <td>{appSettings.FontFamily}</td>
                <td>{appSettings.Theme}</td>
                <td>{appSettings.NavigationBar}</td>
                <td className="action-column">
                  <button
                    key={i}
                    className="button-green"
                    onClick={() => setShowEdit(!showEdit)}
                  >
                    Edit
                  </button>
                </td>
                <td>{showEdit ? <EditApplicationSettings /> : null}</td>
              </tr>
            ))}
          </tbody>

How can I make that each button have different state?

2 Answers

Your state should be index of active row

      const [activeIndex, setActiveIndex] = useState(null);

      <tbody>
        {appSettingsList.map((appSettings, i) => (
          <tr key={i}>
            <td>{appSettings.Name}</td>
            <td>{appSettings.BackgroundColor}</td>
            <td>{appSettings.FontSize}</td>
            <td>{appSettings.FontFamily}</td>
            <td>{appSettings.Theme}</td>
            <td>{appSettings.NavigationBar}</td>
            <td className="action-column">
              <button
                key={i}
                className="button-green"
                onClick={() => setActiveIndex(i)}
              >
                Edit
              </button>
            </td>
            <td>{activeIndex === i ? ( <button key={i} className="button-green" onClick={() => setActiveIndex(null)} > Edit </button> ) : ( <button key={i} className="button-green" onClick={() => setActiveIndex(i)} > Edit </button> )}</td>
          </tr>
        ))}
      </tbody>

You need to handle the edit logic for each row independently.

  1. Create a TableRow component with toggling Edit View logic.
const TableRow = ({ appSettings, i }) => {
    const [showEdit, setShowEdit] = useState([]);

    return (
        <tr key={i}>
            <td>{appSettings.Name}</td>
            <td>{appSettings.BackgroundColor}</td>
            <td>{appSettings.FontSize}</td>
            <td>{appSettings.FontFamily}</td>
            <td>{appSettings.Theme}</td>
            <td>{appSettings.NavigationBar}</td>
            <td className="action-column">
                <button
                    key={i}
                    className="button-green"
                    onClick={() => setShowEdit(!showEdit)}
                >
                    Edit
                </button>
            </td>
            <td>{showEdit ? <EditApplicationSettings /> : null}</td>
        </tr>
    );
};
  1. Iterate over TableRow elements.
<tbody>
    {appSettingsList.map((appSettings, i) => (
        <TableRow appSettings={appSettings} i={i} />
    ))}
</tbody>
Related