Akhilesh
Akhilesh

Reputation: 1303

Reactjs add onClick attribute on a dynamic element

I trying to create a table dynamically from the data received from an ajax response in a react app. The loop is created from the response of an ajax request inside the useEffect hook. The problem is that I can't make work the onClick attribute in an anchor tag in a table cell. Below is the code.

res.data.users.forEach(function (user) {
          let row = table.insertRow(rowcnt);
          let cell1 = row.insertCell(0);
          let cell2 = row.insertCell(1);
          let cell3 = row.insertCell(2);
          cell1.innerHTML = user.u_id;
          cell2.innerHTML = user.username;
          cell3.innerHTML = '<a href="javascript:void(0)"><span data-feather="edit"></span></a><a href="javascript:void(0)" onClick={(e) => deleteUser(e, ' + user.id + ')}><span data-feather="trash"></span></a>';
          rowcnt++;
        });

But in the frontend it is showing

enter image description here

Please help.

Upvotes: 0

Views: 1547

Answers (2)

Andy
Andy

Reputation: 63524

The "React way" is to use:

  1. state to maintain the data.

  2. map to iterate over the user data held in state and produce array of HTML for each user. Add an id to each tr element.

  3. filter in deleteUser function to filter out the row data where the u_ids don't match the id of the deleted row, and use that array to update the state at which point the component will be re-rendered with the updated state.

const { useState } = React;

function Example({ data }) {

  const [ users, setUsers ] = useState(data.users);

  function deleteUser(id) {
    // Call Axios with the id to delete that item
    const filtered = users.filter(user => user.u_id !== id);
    setUsers(filtered);
  }

  function getRows(users) {
    return users.map(user  => {
      const { u_id, username } = user;
      return (
        <tr key={u_id} id={u_id}>
          <td>{u_id}</td>
          <td>{username}</td>
          <td class="delete">
            <a onClick={() => deleteUser(u_id)}>Delete</a>
          </td>
        </tr>
      )
    });
  }

  return (
    <table>
     {getRows(users)}
    </table>
  );
};

const data = {
  users: [
    {u_id: 1, username: 'Steve'},
    {u_id: 2, username: 'Polly'},
    {u_id: 3, username: 'Brian'},
    {u_id: 4, username: 'Billy Joel'}
  ]
};

ReactDOM.render(
  <Example data={data} />,
  document.getElementById("react")
);
.delete { background-color: red; cursor:pointer; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Upvotes: 3

Shemea Xu
Shemea Xu

Reputation: 1

I think you should use jsx to instead of innerHTML, like this:

return (
  <table>
    <thead>
      <tr>
        <th>u_id</th>
        <th>usename</th>
        <th>action</th>
      </tr>
    </thead>
    <tbody>
      {res.data.users.map(user => (
        <tr>
          <td>{user.u_id}</td>
          <td>{user.username}</td>
          <td>
            <a onClick={(e) => deleteUser(e, ' + user.id + ')}>delete</a>
          </td>
        </tr>
      )}
    </tbody>
  </table>
)

Upvotes: 0

Related Questions