1

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 2

3

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>
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the answer. I have tested it and the onclick does not trigger all rows now. However, by using this method, the state cannot be reverse back by the same onclick event. So i made some changes.
{activeIndex === i ? ( <button key={i} className="button-green" onClick={() => setActiveIndex(!i)} > Edit </button> ) : ( <button key={i} className="button-green" onClick={() => setActiveIndex(i)} > Edit </button> )}
2

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>

2 Comments

@alep, let me know if you have any issues with this solution
Thank you for the answer, I have tested it and it works. Is separating the rows to another component is better code management than the one suggest by @iamhyunq?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.