jfrye
jfrye

Reputation: 437

React-router: Using <Link> as clickable data table row

I'm new to using ReactJS and react-router. I want a clickable table row and something like the following setup:

<Link to=“#”>
<tr>
    <td>{this.props.whatever1}</td>
    <td>{this.props.whatever2}</td>
    <td>{this.props.whatever3}</td>
</tr>
</Link>

but I know you can't put <a> tags between the <tbody> and <tr> tags. How else can I accomplish this?

PS: I prefer not to use jQuery if possible.

Upvotes: 29

Views: 40091

Answers (5)

Oleksandr Bondarchuk
Oleksandr Bondarchuk

Reputation: 1053

You can use useHistory() hook:

Declare:

const history = useHistory();

and use it with <tr> or <td> tag:

<tr onClick={() => history.push("/yoururl")}>
    <td>{this.props.whatever1}</td>
    <td>{this.props.whatever2}</td>
    <td>{this.props.whatever3}</td>
</tr>

Upvotes: 0

Prashant Raj
Prashant Raj

Reputation: 192

This answers is based on @Igor Barbasin suggestion. This will add the link to the whole row instead of just the content and we also don't need to wrap all the individual 'td' element with 'Link'.

.table-row {
  display: table-row
}
export default function Table() {
  return (
    <table>
        <thead>
            <tr>
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
            {/* treats the link element as a table row element */}
            <Link className="table-row">
                <td>Noname</td>
            </Link>
        </tbody>
    </table>
  )
}

Upvotes: 5

Malik Ali
Malik Ali

Reputation: 1

{shipment.assets.map((i, index) => (
                              <tr
                                style={{ cursor: "pointer" }}
                                onClick={(e) => e.preventDefault()}
                              >
                                <td>{index + 1}</td>
                                <td>{i._id}</td>
                                <td>{i.status}</td>
                                <td></td>
                              </tr>
                            ))}

Upvotes: -3

Igor Barbashin
Igor Barbashin

Reputation: 921

onClick works, but sometimes you need an actual <a> tag for various reasons:

  • Accessibility
  • Progressive enhancement (if script is throwing an error, links still work)
  • Ability to open a link in new tab
  • Ability to copy the link

Here's an example of a Td component that accepts to prop:

import React from 'react';
import { Link } from 'react-router-dom';

export default function Td({ children, to }) {
  // Conditionally wrapping content into a link
  const ContentTag = to ? Link : 'div';

  return (
    <td>
      <ContentTag to={to}>{children}</ContentTag>
    </td>
  );
}

Then use the component like this:

const users = this.props.users.map((user) =>
      <tr key={user.id}>
        <Td to={`/users/${user.id}/edit`}>{user.name}</Td>
        <Td to={`/users/${user.id}/edit`}>{user.email}</Td>
        <Td to={`/users/${user.id}/edit`}>{user.username}</Td>
      </tr>
    );

Yes, you'll have to pass to prop multiple times, but at the same you have more control over the clickable areas and you may have other interactive elements in the table, like checkboxes.

Upvotes: 25

Sergio Flores
Sergio Flores

Reputation: 5427

Why don't you just use onClick?

var ReactTable = React.createClass({
  handleClick: function(e) {
    this.router.transitionTo('index');
  },
  render: function() {
    return(
      <div>
        <table>
          <thead>
            <tr>
              <th>Name</th>
              <th>Age</th>
              <th>Full Detail</th>
            </tr>
          </thead>
            <tbody>
              <tr onClick={this.handleClick.bind(this)}>
                <td>{user.name}</td>
                <td>{user.age}</td>
                <td>{details}</td>
              </tr>
            </tbody>
        </table>
      </div>
    );
  }
});

Upvotes: 6

Related Questions