繁体   English   中英

React - 在表格行上触发点击事件

[英]React - Triggering click event on table row

我无法从 React 中的表行调用单击事件。 下面是我的代码。 我有一个单独的 function 来单独填充行,但似乎我把绑定信息弄乱了。

import React, {Component, PropTypes} from 'react';
import Header from './Header';

export default class SongData extends Component {
 constructor(props, context) {
    super(props, context);
 }

isEmpty(obj) {
    return Object.keys(obj).length === 0;
}

fetchDetails(song) {
    console.log(song);
}

renderResultRows(data) {
    var self = this;
    return data.map(function(song) {
        return (
            <tr onClick={self.fetchDetails(song)}>
                <td data-title="Song">{song.S_SONG}</td>
                <td data-title="Movie">{song.S_MOVIE}</td>
                <td data-title="Year">{song.S_YEAR}</td>
            </tr>
        );
    }.bind(this));
}

render() {
    return (
        <div id="no-more-tables">
            <table className="table table-hover table-bordered table-striped">
                <thead>
                    <tr>
                        <th>Song</th>
                        <th>Movie</th>
                        <th>Year</th>
                    </tr>
                </thead>
                <tbody>
                    {!this.isEmpty(this.props.searchResult)
                        ? this.renderResultRows(this.props.searchResult)
                        : ''}
                </tbody>
            </table>
        </div>
    );
}

}

首先,您将评估的函数调用传递给您的onClick属性。

单独看下面的代码:

 function foo(name) { return 'hello ' + name; }

 foo('bob');

您希望foo('bob')的输出是“hello bob”。

如果我将它传递给onClick道具,则完全相同。 例如:

 <button onClick={foo('bob')}

在这种情况下,我只会将一个字符串传递给按钮的onClick道具。 onClick (和其他事件道具)期望提供一个函数(或引用)。 我将在下面举一个例子。

其次,我认为您尝试使用const self = thisbind的组合来维护函数的正确范围是正确的。 使用 ES6/2015 中的匿名函数有一种更简单的方法,它始终保持声明它们的范围。

然后我可以将您的代码更新为以下内容:

renderResultRows(data) {
    return data.map((song) => {  // anon func maintains scope!
        // Pass in a function to our onClick, and make it anon
        // to maintain scope.  The function body can be anything
        // which will be executed on click only.  Our song value
        // is maintained via a closure so it works.
        return (
            <tr onClick={() => this.fetchDetails(song)}>
                <td data-title="Song">{song.S_SONG}</td>
                <td data-title="Movie">{song.S_MOVIE}</td>
                <td data-title="Year">{song.S_YEAR}</td>
            </tr>
        );
    });  // no need to bind with anon function
}

但这仍然不是最优的。 当使用像这样的匿名语法(例如<foo onClick={() => { console.log('clicked') } )时,我们在每次渲染时创建一个新函数。 如果您使用纯组件(即仅在提供新 prop 实例时才应重新渲染的组件 - 此检查通过浅比较执行),这可能是一个问题。 总是尝试尽早创建你的函数,例如在构造函数中或通过类属性,如果你使用 babel stage 1,这样你总是传入相同的引用。

但是,对于您的示例,您需要将一个值“传递到”每个onClick处理程序中。 为此,您可以使用以下方法:

fetchSongDetails = () => {
  const song = e.target.getAttribute('data-item');
  console.log('We need to get the details for ', song);
}

renderResultRows(data) {
    return data.map((song, index) => {  // anon func maintains scope!
        // Pass in a function to our onClick, and make it anon
        // to maintain scope.  The function body can be anything
        // which will be executed on click only.  Our song value
        // is maintained via a closure so it works.
        return (
            <tr key={index} data-item={song} onClick={this.fetchSongDetails}>
                <td data-title="Song">{song.S_SONG}</td>
                <td data-title="Movie">{song.S_MOVIE}</td>
                <td data-title="Year">{song.S_YEAR}</td>
            </tr>
        );
    });  // no need to bind with anon function
}

这是一个更好的方法。 另请注意,我为正在生成的每一行添加了一个key prop。 这是另一个反应最佳实践,因为反应将在其差异算法中使用唯一的密钥标识符。


我强烈推荐以下阅读:

除了@ctrlplusb answer 之外,我还想建议另一种在 click 事件中传递对象的方法:

// 歌曲组件

import React from 'react';
import RowComponent from './RowComponent';

export default class SongData extends React.PureComponent {

  fetchDetails(songObj) {
    // whatever
  }

  renderResultRows(data) {
    return data.map(songObj => (
      <RowComponent
        key={songObj.id}
        data={songObj}
        onClick={this.fetchDetails}
      />;
  }

  render() {

    const { data } = this.props;

    return (
      <div>
        <table>
         <thead>
         </thead>
         <tbody>
          {
            this.renderResultRows(data)
          }
         </tbody>
        </table>
      </div>
    );
  }
}

// 行组件

import React from 'react';

export function RowComponent(props) {
  const { data, onClick } = props;

  function handleClick() {
    onClick(data);
  }

  return (
    <tr onClick={handleClick}>
      <td data-title="Song">{data.S_SONG}</td>
      <td data-title="Movie">{data.S_MOVIE}</td>
      <td data-title="Year">{data.S_YEAR}</td>
    </tr>
  );
}

使用变量绑定来避免在渲染时调用函数: self.fetchDetails.bind(song)

if you need to turn off the onClick for row selection on a single column of a row.
One of the columns in my table contain buttons for the user to interact with. you does not want the clicking of these buttons to trigger the select row, but clicking any other column should. 

 you can try to call e.stopPropagation() when handling the click event of your custom buttons.

ex--                     <TableRow hover
                          role="checkbox"
                          tabIndex={-1}
                          key={id}
                          onClick={() => navigate(`/collection-info/${id}`)}
                          className="cursor-pointer"
                        >
                          <TableCell align={labels.align}>
                            {name}
                          </TableCell>
                          <TableCell align={labels.align}>
                            {size}
                          </TableCell>
                          <TableCell align={labels.align}>
                            { categories.join(",")}
                          </TableCell>
                          <TableCell align={labels.align}>
                            { blockchain}
                          </TableCell>
                          <TableCell align={labels.align}>
                            {list_marketplace ? "Enabled" : "Disabled"}
                          </TableCell>
                          <TableCell
                            align={labels.align}
                            onClick={(e) => e.stopPropagation()}
                          >
                            {FaEdit && (
                              <DashboardPopup
                                setShow={setShow}
                                setEditCollection={setEditCollection}
                                setGetCollection={setGetCollection}
                                collectionTable={collectionTable}
                                id={id}
                                setDeleteCollection={setDeleteCollection}
                              />
                            )}
                          </TableCell>
                        </TableRow>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM