Phản ứng js onClick không thể chuyển giá trị cho phương thức


639

Tôi muốn đọc các thuộc tính giá trị sự kiện onClick. Nhưng khi tôi nhấp vào nó, tôi thấy một cái gì đó như thế này trên bảng điều khiển:

SyntheticMouseEvent {dispatchConfig: Object, dispatchMarker: ".1.1.0.2.0.0:1", nativeEvent: MouseEvent, type: "click", target

Mã của tôi đang hoạt động chính xác. Khi tôi chạy, tôi có thể thấy {column}nhưng không thể tải nó trong sự kiện onClick.

Mã của tôi:

var HeaderRows = React.createClass({
  handleSort:  function(value) {
    console.log(value);
  },
  render: function () {
    var that = this;
    return(
      <tr>
        {this.props.defaultColumns.map(function (column) {
          return (
            <th value={column} onClick={that.handleSort} >{column}</th>
          );
        })}
        {this.props.externalColumns.map(function (column) {
          // Multi dimension array - 0 is column name
          var externalColumnName = column[0];
          return ( <th>{externalColumnName}</th>);
        })}
      </tr>
    );
  }
});

Làm cách nào tôi có thể chuyển một giá trị cho onClicksự kiện trong React js?



2
xem xét sử dụng bản thân thay vì đó. Điều đó khá dễ gây hiểu lầm vì nó phải đồng nghĩa với "cái này" (mặc dù thực sự không quan trọng đối với mỗi người)
Dan

Sử dụng phương thức liên kết và phương pháp mũi tên, chúng ta có thể chuyển giá trị cho sự kiện Onclick
Merugu Prashanth

Câu trả lời:


1286

Cách dễ dàng

Sử dụng chức năng mũi tên:

return (
  <th value={column} onClick={() => this.handleSort(column)}>{column}</th>
);

Điều này sẽ tạo ra một chức năng mới gọi handleSort với các thông số phù hợp.

Cách tốt hơn

Trích xuất nó thành một thành phần phụ. Vấn đề với việc sử dụng chức năng mũi tên trong lệnh gọi kết xuất là nó sẽ tạo ra một chức năng mới mỗi lần, điều này dẫn đến việc tái hiện không cần thiết.

Nếu bạn tạo một thành phần phụ, bạn có thể chuyển trình xử lý và sử dụng đạo cụ làm đối số, sau đó sẽ chỉ hiển thị lại khi đạo cụ thay đổi (vì tham chiếu trình xử lý bây giờ không bao giờ thay đổi):

Thành phần phụ

class TableHeader extends Component {
  handleClick = () => {
    this.props.onHeaderClick(this.props.value);
  }

  render() {
    return (
      <th onClick={this.handleClick}>
        {this.props.column}
      </th>
    );
  }
}

Thành phần chính

{this.props.defaultColumns.map((column) => (
  <TableHeader
    value={column}
    onHeaderClick={this.handleSort}
  />
))}

Cách dễ dàng cũ (ES5)

Sử dụng .bindđể truyền tham số bạn muốn:

return (
  <th value={column} onClick={that.handleSort.bind(that, column)}>{column}</th>
);

7
Phản ứng đưa ra cảnh báo khi tôi sử dụng như mã của bạn. Tôi thay đổi mã của mình thành onClick = {that.onClick.bind (null, cột)}
user1924375

12
Bạn sẽ sử dụng <a>thẻ này như thế nào với thẻ nơi bạn cần vượt qua sự kiện để sử dụngpreventDefault()
Simon H

38
@SimonH Sự kiện sẽ được thông qua dưới dạng đối số cuối cùng, sau các đối số bạn chuyển qua bind.
smudge

47
Đây không phải là xấu cho hiệu suất? Sẽ không có một chức năng mới được tạo ra trên mỗi kết xuất?
AndrewMcLagan

13
@AndrewMcLagan Đó là. Tôi tìm thấy điều này để mô tả các quy tắc và giải pháp hiệu quả nhất.
E. Sundin

140

Có những câu trả lời hay ở đây, và tôi đồng ý với @Austin Greco (tùy chọn thứ hai với các thành phần riêng biệt)
Có một cách khác tôi thích, cà ri .
Những gì bạn có thể làm là tạo một hàm chấp nhận một tham số (tham số của bạn) và trả về một hàm khác chấp nhận tham số khác (sự kiện nhấp trong trường hợp này). sau đó bạn có thể tự do làm với nó những gì bạn muốn.

ES5:

handleChange(param) { // param is the argument you passed to the function
    return function (e) { // e is the event object that returned

    };
}

ES6:

handleChange = param => e => {
    // param is the argument you passed to the function
    // e is the event object that returned
};

Và bạn sẽ sử dụng nó theo cách này:

<input 
    type="text" 
    onChange={this.handleChange(someParam)} 
/>

Dưới đây là một ví dụ đầy đủ về việc sử dụng như vậy:

Lưu ý rằng phương pháp này không giải quyết việc tạo một thể hiện mới trên mỗi kết xuất.
Tôi thích cách tiếp cận này hơn các trình xử lý nội tuyến khác vì theo tôi cách này ngắn gọn và dễ đọc hơn.

Chỉnh sửa:
Như được đề xuất trong các bình luận bên dưới, bạn có thể lưu trữ / ghi nhớ kết quả của chức năng.

Đây là một thực hiện ngây thơ:


12
Đây phải là câu trả lời được chấp nhận. Thực sự dễ thực hiện và bạn không cần phải tạo bất kỳ thành phần nào khác hoặc ràng buộc khác nhau. Cảm ơn bạn!
Tamb

29
Nhìn có vẻ tốt hơn, nhưng từ góc độ hiệu năng, việc currying không thực sự hữu ích, bởi vì nếu bạn gọi handChange hai lần, với cùng một param, bạn sẽ có hai hàm mà công cụ JS coi là các đối tượng riêng biệt, ngay cả khi chúng làm cùng một việc . Vì vậy, bạn vẫn nhận được một kết xuất lại. Vì lợi ích của hiệu suất, bạn sẽ cần lưu trữ kết quả của handChange để có được lợi thế về hiệu suất. ThíchhandleChange = param => cache[param] || (e => { // the function body })
travellingprog

6
Đây là câu trả lời hoàn hảo nếu bạn thực hiện lời khuyên từ @travellingprog
llioor

2
Bất cứ ai cũng có thể cung cấp một liên kết hoặc giải thích làm thế nào cơ chế bộ đệm này hoạt động? cảm ơn.
Sadok Mtir

2
Đẹp và gọn gàng!
HHR Alimam

117

Ngày nay, với ES6, tôi cảm thấy chúng ta có thể sử dụng một câu trả lời được cập nhật.

return (
  <th value={column} onClick={()=>this.handleSort(column)} >{column}</th>
);

Về cơ bản, (đối với bất kỳ ai không biết) vì onClickđang mong đợi một chức năng được truyền cho nó, bindhoạt động vì nó tạo ra một bản sao của chức năng. Thay vào đó, chúng ta có thể truyền một biểu thức hàm mũi tên chỉ đơn giản gọi hàm chúng ta muốn và bảo tồn this. Bạn không bao giờ cần phải liên kết renderphương thức trong React, nhưng nếu vì lý do nào đó bạn bị mất thismột trong các phương thức thành phần của mình:

constructor(props) {
  super(props);
  this.myMethod = this.myMethod.bind(this);
}

10
Bạn không bao giờ cần phải liên kết render()bởi vì nó được gọi bởi React. Nếu bất cứ điều gì, bạn cần phải bindxử lý sự kiện và chỉ khi bạn không sử dụng mũi tên.
Dan Abramov

1
@DanAbramov Tôi nghĩ bạn đúng, nhưng tôi đã đưa nó vào trong trường hợp - được cập nhật với một ví dụ không hoàn toàn khuyến khích kết xuất kết xuất.
aikeru

3
Lưu ý rằng tốt nhất là chuyển propsđến super()hoặc this.propssẽ không được xác định trong quá trình xây dựng có thể gây nhầm lẫn.
Dan Abramov

2
Để đạt được điều gì? Bạn có thể định nghĩa một trình xử lý bên trong thành phần chức năng và vượt qua nó. Nó sẽ là một chức năng khác nhau cho mỗi kết xuất, vì vậy nếu bạn đã xác định với một trình lược tả rằng nó cung cấp cho bạn các vấn đề hoàn hảo (và chỉ khi bạn thực sự chắc chắn trong việc này!), Hãy xem xét sử dụng một lớp thay thế.
Dan Abramov

1
@ me-me Có, và nếu bạn chọn tham gia JavaScript trong Babel, bạn chỉ nên khai báo các thuộc tính trên lớp của mình foo = () => {...}và sau đó tham chiếu trong <button onClick={this.foo}...lý do duy nhất để bao gồm hàm mũi tên nếu bạn sử dụng babel theo cách này, IMO, là nếu bạn muốn nắm bắt một số biến chỉ tồn tại trong phạm vi phương thức render () (các sự kiện chỉ có thể được truyền qua và không áp dụng).
aikeru

73

[[h / t đến @ E.Sundin để liên kết này trong một bình luận]

Câu trả lời hàng đầu (hàm ẩn danh hoặc ràng buộc) sẽ hoạt động, nhưng nó không phải là hiệu suất cao nhất, vì nó tạo ra một bản sao của trình xử lý sự kiện cho mọi trường hợp được tạo bởi map() hàm.

Đây là một lời giải thích về cách tối ưu để thực hiện nó từ phản hồi của plugin -intint :

Danh sách các mặt hàng

Trường hợp sử dụng phổ biến của liên kết trong kết xuất là khi kết xuất danh sách, để có một cuộc gọi lại riêng cho mỗi mục danh sách:

const List = props => (
      <ul>
        {props.items.map(item =>
          <li key={item.id} onClick={() => console.log(item.id)}>
            ...
          </li>
        )}
      </ul>
    );

Thay vì làm theo cách này, hãy kéo phần lặp lại vào thành phần của chính nó:

const List = props => (
      <ul>
        {props.items.map(item =>
          <ListItem 
            key={item.id} 
            item={item} 
            onItemClick={props.onItemClick} // assume this is passed down to List
           />
        )}
      </ul>
    );


const ListItem = props => {
  const _onClick = () => {
    console.log(props.item.id);
  }
    return (
      <li onClick={_onClick}>
        ...
      </li>
    );

});

Điều này sẽ tăng tốc độ kết xuất, vì nó tránh được nhu cầu tạo các chức năng mới (thông qua các cuộc gọi liên kết) trên mỗi kết xuất.


Phản ứng có gọi các chức năng đó bằng cuộc gọi / áp dụng, sau đó, dưới mui xe và tránh sử dụng liên kết nội bộ không?
aikeru

1
Có cách nào để làm điều này bằng cách sử dụng một thành phần không trạng thái?
Carlos Martinez

2
@CarlosMartinez tốt mắt, tôi đã cập nhật ví dụ - chúng phải là thành phần chức năng không trạng thái (SFC) ngay từ đầu. Nói chung, nếu một thành phần không bao giờ sử dụng this.state, bạn có thể trao đổi nó một cách an toàn với SFC.
Brandon

3
Hmm, tôi không hiểu làm thế nào điều này là hiệu quả hơn? Chức năng ListItem sẽ không được gọi mỗi lần và do đó, hàm _onClick sẽ được tạo mỗi lần kết xuất.
Mattias Petter Johansson

1
Tôi ở xa một chuyên gia ở đây, nhưng theo tôi hiểu, trong mẫu 'chính xác', chỉ có một phiên bản của trình xử lý và nó đã vượt qua sự ủng hộ cho bất kỳ trường hợp nào của thành phần gọi nó. Trong ví dụ liên kết (nghĩa là mẫu 'sai'), có một phiên bản của trình xử lý cho mọi thành phần được khởi tạo. Đó là loại bộ nhớ tương đương với việc viết cùng một chức năng ba mươi lần ngược lại viết một lần và gọi nó khi cần thiết.
Brandon

25

Đây là cách tiếp cận của tôi, không chắc nó tệ như thế nào, hãy bình luận

Trong phần tử có thể nhấp

return (
    <th value={column} onClick={that.handleSort} data-column={column}>   {column}</th>
);

và sau đó

handleSort(e){
    this.sortOn(e.currentTarget.getAttribute('data-column'));
}

Đây là một cách tiếp cận tôi đã nghĩ đến, nó cảm thấy một chút hack nhưng tránh tạo ra một thành phần mới. Tôi không chắc chắn nếu getAttribution tốt hơn hay kém hoàn hảo hơn so với việc kéo vào một thành phần riêng biệt.
kamranicus

2
Tôi nghĩ đó là một giải pháp tốt vì nó rất đơn giản. Nhưng nó chỉ hoạt động với các giá trị chuỗi, nếu bạn muốn một đối tượng thì nó không hoạt động.
Stephane L

Đối với một đối tượng bạn sẽ cần phải làm encodeURIComponent(JSON.stringify(myObj)), sau đó phân tích nó , JSON.parse(decodeURIComponent(myObj)). Đối với các hàm Tôi khá chắc chắn điều này sẽ không hoạt động nếu không có eval hoặc Hàm mới (), cả hai đều nên tránh. Vì những lý do này, tôi không sử dụng các thuộc tính dữ liệu để truyền dữ liệu trong React / JS.
Solvitieg

Tôi muốn thêm Tôi không sử dụng điều này thường xuyên và chỉ cho những thứ nhỏ nhặt. Nhưng thông thường tôi chỉ tạo một thành phần và truyền dữ liệu dưới dạng đạo cụ cho nó. Sau đó, xử lý nhấp chuột bên trong thành phần mới đó hoặc truyền chức năng onClick cho thành phần đó. Like được giải thích trong câu trả lời của Brandon
Santiago Ramirez

1
tập dữ liệu có thể được truy cập trực tiếp theo cách này trên các trình duyệt hiện đại (bao gồm IE11): e.cienTarget.dataset.column
gsziszi

17

ví dụ này có thể hơi khác với bạn. nhưng tôi có thể đảm bảo với bạn rằng đây là giải pháp tốt nhất bạn có thể có cho vấn đề này. tôi đã tìm kiếm nhiều ngày cho một giải pháp không có vấn đề về hiệu suất. và cuối cùng đã đưa ra cái này

class HtmlComponent extends React.Component {
  constructor() {
    super();
    this.state={
       name:'MrRehman',
    };
    this.handleClick= this.handleClick.bind(this);
  }

  handleClick(event) {
    const { param } = e.target.dataset;
    console.log(param);
    //do what you want to do with the parameter
  }

  render() {
    return (
      <div>
        <h3 data-param="value what you wanted to pass" onClick={this.handleClick}>
          {this.state.name}
        </h3>
      </div>
    );
  }
}

CẬP NHẬT

trong trường hợp bạn muốn xử lý các đối tượng được coi là tham số. bạn có thể sử dụng JSON.stringify(object)để chuyển đổi nó thành chuỗi và thêm vào tập dữ liệu.

return (
   <div>
     <h3 data-param={JSON.stringify({name:'me'})} onClick={this.handleClick}>
        {this.state.name}
     </h3>
   </div>
);

1
điều này không hoạt động khi dữ liệu được truyền là một đối tượng
SlimSim

sử dụng JSON.opesify để khắc phục sự cố. @SlimSim. nên làm điều đó
hannad

Nếu bạn cần sử dụng JSON.opesify cho vấn đề này thì có lẽ đây không phải là phương pháp đúng. Quá trình xâu chuỗi mất rất nhiều bộ nhớ.
KFE

trong hầu hết các trường hợp, bạn sẽ chỉ chuyển ID dưới dạng params và lấy chi tiết đối tượng dựa trên ID đó từ đối tượng nguồn của bạn. và tại sao và làm thế nào nó chiếm nhiều bộ nhớ, tôi biết JSON stringify là chậm, nhưng nhấp chuột Fn là không đồng bộ và nó sẽ không có hoặc có hiệu lực 0 đối với dom, một khi được xây dựng
hannad Rehman

6
class extends React.Component {
    onClickDiv = (column) => {
        // do stuff
    }
    render() {
        return <div onClick={() => this.onClickDiv('123')} />
    }
}

2
Giống nhau - DOM mới trên mỗi kết xuất. Vì vậy, React sẽ cập nhật DOM mỗi lần.
Alex Shwarc

4

Thêm một lựa chọn không liên quan .bindhoặc ES6 là sử dụng một thành phần con với trình xử lý để gọi trình xử lý cha mẹ với các đạo cụ cần thiết. Dưới đây là một ví dụ (và một liên kết đến ví dụ hoạt động bên dưới):

var HeaderRows = React.createClass({
  handleSort:  function(value) {
     console.log(value);
  },
  render: function () {
      var that = this;
      return(
          <tr>
              {this.props.defaultColumns.map(function (column) {
                  return (
                      <TableHeader value={column} onClick={that.handleSort} >
                        {column}
                      </TableHeader>
                  );
              })}
              {this.props.externalColumns.map(function (column) {
                  // Multi dimension array - 0 is column name
                  var externalColumnName = column[0];
                  return ( <th>{externalColumnName}</th>
                  );
              })}
          </tr>);
      )
  }
});

// A child component to pass the props back to the parent handler
var TableHeader = React.createClass({
  propTypes: {
    value: React.PropTypes.string,
    onClick: React.PropTypes.func
  },
  render: function () {
    return (
      <th value={this.props.value} onClick={this._handleClick}
        {this.props.children}
      </th>
    )        
  },
  _handleClick: function () {
    if (this.props.onClick) {
      this.props.onClick(this.props.value);
    }
  }
});

Ý tưởng cơ bản là để thành phần cha mẹ truyền onClickchức năng cho thành phần con. Thành phần con gọi onClickhàm và có thể truy cập bất kỳ propsđược truyền cho nó (và event), cho phép bạn sử dụng bất kỳ eventgiá trị hoặc đạo cụ nào khác trong hàm chaonClick hàm .

Đây là bản demo CodePen hiển thị phương thức này đang hoạt động.


4

Thực hiện một nỗ lực thay thế để trả lời câu hỏi của OP, bao gồm các cuộc gọi e.preventDefault ():

Liên kết được kết xuất ( ES6 )

<a href="#link" onClick={(e) => this.handleSort(e, 'myParam')}>

Chức năng thành phần

handleSort = (e, param) => {
  e.preventDefault();
  console.log('Sorting by: ' + param)
}

4

Tôi nhận ra điều này là khá muộn cho bữa tiệc, nhưng tôi nghĩ một giải pháp đơn giản hơn nhiều có thể đáp ứng nhiều trường hợp sử dụng:

    handleEdit(event) {
        let value = event.target.value;
    }

    ...

    <button
        value={post.id}
        onClick={this.handleEdit} >Edit</button>

Tôi đoán bạn cũng có thể sử dụng một data- thuộc tính.

Đơn giản, ngữ nghĩa.


4

Đơn giản chỉ cần tạo một chức năng như thế này

  function methodName(params) {
    //the thing  you wanna do
  }

và gọi nó ở nơi bạn cần

<Biểu tượng onClick = {() => {methodName (theParamsYouwantToPass); }} />


3

Bạn chỉ có thể làm điều đó nếu bạn đang sử dụng ES6.

export default class Container extends Component {
  state = {
    data: [
        // ...
    ]
  }

  handleItemChange = (e, data) => {
      // here the data is available 
      // ....
  }
  render () {
     return (
        <div>
        {
           this.state.data.map((item, index) => (
              <div key={index}>
                  <Input onChange={(event) => this.handItemChange(event, 
                         item)} value={item.value}/>
              </div>
           ))
        }
        </div>
     );
   }
 }

3

Việc thực hiện hiển thị tổng số đếm từ một đối tượng bằng cách chuyển số đếm dưới dạng tham số từ thành phần chính sang thành phần phụ như được mô tả bên dưới.

Đây là MainComponent.js

import React, { Component } from "react";

import SubComp from "./subcomponent";

class App extends Component {

  getTotalCount = (count) => {
    this.setState({
      total: this.state.total + count
    })
  };

  state = {
    total: 0
  };

  render() {
    const someData = [
      { name: "one", count: 200 },
      { name: "two", count: 100 },
      { name: "three", count: 50 }
    ];
    return (
      <div className="App">
        {someData.map((nameAndCount, i) => {
          return (
            <SubComp
              getTotal={this.getTotalCount}
              name={nameAndCount.name}
              count={nameAndCount.count}
              key={i}
            />
          );
        })}
        <h1>Total Count: {this.state.total}</h1>
      </div>
    );
  }
}

export default App;

Và đây là SubComp.js

import React, { Component } from 'react';
export default class SubComp extends Component {

  calculateTotal = () =>{
    this.props.getTotal(this.props.count);
  }

  render() {
    return (
      <div>
        <p onClick={this.calculateTotal}> Name: {this.props.name} || Count: {this.props.count}</p>
      </div>
    )
  }
};

Hãy thử thực hiện ở trên và bạn sẽ nhận được kịch bản chính xác về cách các tham số hoạt động trong Reacjs trên bất kỳ phương thức DOM nào.


3

Tôi đã viết một thành phần bao bọc có thể được sử dụng lại cho mục đích này dựa trên các câu trả lời được chấp nhận ở đây. Tuy nhiên, nếu tất cả những gì bạn cần làm là vượt qua một chuỗi, thì chỉ cần thêm thuộc tính dữ liệu và đọc nó từ e.target.dataset (như một số người khác đã đề xuất). Theo mặc định, trình bao bọc của tôi sẽ liên kết với bất kỳ prop nào là hàm và bắt đầu bằng 'bật' và tự động chuyển dữ liệu prop trở lại cho người gọi sau tất cả các đối số sự kiện khác. Mặc dù tôi chưa kiểm tra hiệu năng, nhưng nó sẽ cho bạn cơ hội để tránh tự tạo lớp và nó có thể được sử dụng như thế này:

const DataButton = withData('button')
const DataInput = withData('input');

hoặc cho các thành phần và chức năng

const DataInput = withData(SomeComponent);

hoặc nếu bạn thích

const DataButton = withData(<button/>)

tuyên bố rằng bên ngoài container của bạn (gần hàng nhập khẩu của bạn)

Đây là cách sử dụng trong một container:

import withData from './withData';
const DataInput = withData('input');

export default class Container extends Component {
    state = {
         data: [
             // ...
         ]
    }

    handleItemChange = (e, data) => {
        // here the data is available 
        // ....
    }

    render () {
        return (
            <div>
                {
                    this.state.data.map((item, index) => (
                        <div key={index}>
                            <DataInput data={item} onChange={this.handleItemChange} value={item.value}/>
                        </div>
                    ))
                }
            </div>
        );
    }
}

Đây là mã trình bao bọc 'withData.js:

import React, { Component } from 'react';

const defaultOptions = {
    events: undefined,
}

export default (Target, options) => {
    Target = React.isValidElement(Target) ? Target.type : Target;
    options = { ...defaultOptions, ...options }

    class WithData extends Component {
        constructor(props, context){
            super(props, context);
            this.handlers = getHandlers(options.events, this);        
        }

        render() {
            const { data, children, ...props } = this.props;
            return <Target {...props} {...this.handlers} >{children}</Target>;
        }

        static displayName = `withData(${Target.displayName || Target.name || 'Component'})`
    }

    return WithData;
}

function getHandlers(events, thisContext) {
    if(!events)
        events = Object.keys(thisContext.props).filter(prop => prop.startsWith('on') && typeof thisContext.props[prop] === 'function')
    else if (typeof events === 'string')
        events = [events];

    return events.reduce((result, eventType) => {
        result[eventType] = (...args) => thisContext.props[eventType](...args, thisContext.props.data);
        return result;
    }, {});
}

2

Tôi có dưới 3 đề xuất về vấn đề này trên JSX onClick Events -

  1. Trên thực tế, chúng ta không cần sử dụng hàm .bind () hoặc Mũi tên trong mã của mình. Bạn có thể sử dụng đơn giản trong mã của bạn.

  2. Bạn cũng có thể di chuyển sự kiện onClick từ th (hoặc ul) sang tr (hoặc li) để cải thiện hiệu suất. Về cơ bản, bạn sẽ có n số "Trình lắng nghe sự kiện" cho phần tử n li của bạn.

    So finally code will look like this:
    <ul onClick={this.onItemClick}>
        {this.props.items.map(item =>
               <li key={item.id} data-itemid={item.id}>
                   ...
               </li>
          )}
    </ul>

    // Và bạn có thể truy cập item.idtheo onItemClickphương thức như hình dưới đây:

    onItemClick = (event) => {
       console.log(e.target.getAttribute("item.id"));
    }
  3. Tôi đồng ý với cách tiếp cận được đề cập ở trên để tạo Thành phần React riêng cho ListItem và List. Điều này làm cho mã có vẻ tốt tuy nhiên nếu bạn có 1000 li thì 1000 Trình lắng nghe sự kiện sẽ được tạo. Hãy chắc chắn rằng bạn không nên có nhiều người nghe sự kiện.

    import React from "react";
    import ListItem from "./ListItem";
    export default class List extends React.Component {
    
        /**
        * This List react component is generic component which take props as list of items and also provide onlick
        * callback name handleItemClick
        * @param {String} item - item object passed to caller
        */
        handleItemClick = (item) => {
            if (this.props.onItemClick) {
                this.props.onItemClick(item);
            }
        }
    
        /**
        * render method will take list of items as a props and include ListItem component
        * @returns {string} - return the list of items
        */
        render() {
            return (
                <div>
                  {this.props.items.map(item =>
                      <ListItem key={item.id} item={item} onItemClick={this.handleItemClick}/>
                  )}
                </div>
            );
        }
    
    }
    
    
    import React from "react";
    
    export default class ListItem extends React.Component {
        /**
        * This List react component is generic component which take props as item and also provide onlick
        * callback name handleItemClick
        * @param {String} item - item object passed to caller
        */
        handleItemClick = () => {
            if (this.props.item && this.props.onItemClick) {
                this.props.onItemClick(this.props.item);
            }
        }
        /**
        * render method will take item as a props and print in li
        * @returns {string} - return the list of items
        */
        render() {
            return (
                <li key={this.props.item.id} onClick={this.handleItemClick}>{this.props.item.text}</li>
            );
        }
    }

1
Điều này không hoạt động khi dữ liệu bạn cần truyền là một đối tượng. Thuộc tính sẽ chỉ hoạt động với chuỗi. Ngoài ra đọc từ dom thông qua thuộc tính get có lẽ là một hoạt động đắt tiền hơn.
SlimSim

2

Tôi đã thêm mã cho giá trị sự kiện onclick vào phương thức theo hai cách. 1. sử dụng phương thức liên kết 2. sử dụng phương thức mũi tên (=>). xem các phương thức controlsort1 và controlsort

var HeaderRows  = React.createClass({
    getInitialState : function() {
      return ({
        defaultColumns : ["col1","col2","col2","col3","col4","col5" ],
        externalColumns : ["ecol1","ecol2","ecol2","ecol3","ecol4","ecol5" ],

      })
    },
    handleSort:  function(column,that) {
       console.log(column);
       alert(""+JSON.stringify(column));
    },
    handleSort1:  function(column) {
       console.log(column);
       alert(""+JSON.stringify(column));
    },
    render: function () {
        var that = this;
        return(
        <div>
            <div>Using bind method</div>
            {this.state.defaultColumns.map(function (column) {
                return (
                    <div value={column} style={{height : '40' }}onClick={that.handleSort.bind(that,column)} >{column}</div>
                );
            })}
            <div>Using Arrow method</div>

            {this.state.defaultColumns.map(function (column) {
                return (
                    <div value={column} style={{height : 40}} onClick={() => that.handleSort1(column)} >{column}</div>

                );
            })}
            {this.state.externalColumns.map(function (column) {
                // Multi dimension array - 0 is column name
                var externalColumnName = column;
                return (<div><span>{externalColumnName}</span></div>
                );
            })}

        </div>);
    }
});

2

Dưới đây là ví dụ chuyển giá trị trên sự kiện onClick.

Tôi đã sử dụng cú pháp es6. nhớ trong hàm mũi tên thành phần lớp không liên kết tự động, vì vậy ràng buộc rõ ràng trong hàm tạo.

class HeaderRows extends React.Component {

    constructor(props) {
        super(props);
        this.handleSort = this.handleSort.bind(this);
    }

    handleSort(value) {
        console.log(value);
    }

    render() {
        return(
            <tr>
                {this.props.defaultColumns.map( (column, index) =>
                    <th value={ column } 
                        key={ index } 
                        onClick={ () => this.handleSort(event.target.value) }>
                        { column }
                    </th>
                )}

                {this.props.externalColumns.map((column, index)  =>
                    <th value ={ column[0] }
                        key={ index }>
                        {column[0]}
                    </th>
                )}
            </tr>
         );
    }
}

2

Tôi đoán bạn sẽ phải liên kết phương thức với thể hiện của lớp React. An toàn hơn khi sử dụng hàm tạo để liên kết tất cả các phương thức trong React. Trong trường hợp của bạn khi bạn truyền tham số cho phương thức, tham số đầu tiên được sử dụng để liên kết ngữ cảnh 'this' của phương thức, do đó bạn không thể truy cập giá trị bên trong phương thức.


2
1. You just have to use an arrow function in the Onclick event like this: 

<th value={column} onClick={() => that.handleSort(theValue)} >{column}</th>

2.Then bind this in the constructor method:
    this.handleSort = this.handleSort.bind(this);

3.And finally get the value in the function:
  handleSort(theValue){
     console.log(theValue);
}

2

Có một cách rất dễ dàng.

 onClick={this.toggleStart('xyz')} . 
  toggleStart= (data) => (e) =>{
     console.log('value is'+data);  
 }

2
class TableHeader extends Component {
  handleClick = (parameter,event) => {
console.log(parameter)
console.log(event)

  }

  render() {
    return (
      <button type="button" 
onClick={this.handleClick.bind(this,"dataOne")}>Send</button>
    );
  }
}

4
Mặc dù mã này có thể giải quyết câu hỏi, bao gồm một lời giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn.
Shree

2

Đến từ câu hỏi này, nhưng tôi nghĩ .bindsẽ làm được điều đó. Tìm mã mẫu dưới đây.

const handleClick = (data) => {
    console.log(data)
}

<button onClick={handleClick.bind(null, { title: 'mytitle', id: '12345' })}>Login</button>

1

Sử dụng chức năng mũi tên:

Bạn phải cài đặt giai đoạn 2:

npm cài đặt babel-preset-giai đoạn-2:

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            value=0
        }
    }

    changeValue = (data) => (e) => {
        alert(data);  //10
        this.setState({ [value]: data })
    }

    render() {
        const data = 10;
        return (
            <div>
                <input type="button" onClick={this.changeValue(data)} />
            </div>
        );
    }
}
export default App; 

0

Có 3 cách để xử lý việc này: -

  1. Ràng buộc phương thức trong constructor là: -

    export class HeaderRows extends Component {
       constructor() {
           super();
           this.handleSort = this.handleSort.bind(this);
       }
    }
  2. Sử dụng chức năng mũi tên trong khi tạo nó là: -

    handleSort = () => {
        // some text here
    }
  3. Cách thứ ba là thế này: -

    <th value={column} onClick={() => that.handleSort} >{column}</th>

0

Bạn có thể sử dụng mã của mình như thế này:

<th value={column} onClick={(e) => that.handleSort(e, column)} >{column}</th>

Ở đây e dành cho đối tượng sự kiện, nếu bạn muốn sử dụng các phương thức sự kiện như preventDefault()trong hàm xử lý của bạn hoặc muốn lấy giá trị đích hoặc tên như thế nào e.target.name.


0

Tôi thấy giải pháp chuyển param như một thuộc tính của thẻ khá hợp lý.

Tuy nhiên, nó có những hạn chế:

  • Không hoạt động đúng khi mục danh sách có các thẻ khác (do đó event.target có thể khác với dự định)
  • Param chỉ có thể là một chuỗi. Yêu cầu tuần tự hóa và giải tuần tự hóa.

Đó là lý do tại sao tôi đến với thư viện này: Reac-event-param

Nó:

  • Giải quyết vấn đề của trẻ bằng cách tìm kiếm thuộc tính cần thiết ở cha mẹ bất cứ khi nào cần
  • Tự động tuần tự hóa và giải tuần tự hóa param
  • Đóng gói logic của cài đặt và nhận. Không cần phải lộn xộn với tên param

Ví dụ sử dụng:

import { setEventParam, getEventParam } from "react-event-param";

class List extends Component {
  onItemClick = e => {
    const index = getEventParam(e.target);
    // Do something with index
  };

  render() {
    return (
      <ul>
        {this.props.items.map((itemText, index) => (
          <li
            key={index}
            {...setEventParam(index)}
            onClick={this.onItemClick}
          >
            {{ itemText }}
          </li>
        ))}
      </ul>
    );
  }
}

export default List;

0

Có rất nhiều cân nhắc về hiệu suất, tất cả trong chân không.
Vấn đề với những người xử lý này là bạn cần phải cà ri chúng để kết hợp với đối số mà bạn không thể đặt tên trong các đạo cụ.
Điều này có nghĩa là thành phần cần một trình xử lý cho mỗi và mọi phần tử có thể nhấp. Chúng ta hãy đồng ý rằng đối với một vài nút thì đây không phải là vấn đề, phải không?
Vấn đề phát sinh khi bạn đang xử lý dữ liệu dạng bảng với hàng chục cột và hàng nghìn hàng. Ở đó bạn nhận thấy tác động của việc tạo ra nhiều xử lý đó.

Thực tế là, tôi chỉ cần một.
Tôi đặt trình xử lý ở mức bảng (hoặc UL hoặc OL ...) và khi nhấp chuột xảy ra, tôi có thể biết đó là ô được nhấp bằng dữ liệu có sẵn từ bao giờ trong đối tượng sự kiện:

nativeEvent.target.tagName
nativeEvent.target.parentElement.tagName 
nativeEvent.target.parentElement.rowIndex
nativeEvent.target.cellIndex
nativeEvent.target.textContent

Tôi sử dụng các trường tagname để kiểm tra xem lần nhấp xảy ra trong một yếu tố hợp lệ, ví dụ bỏ qua các lần nhấp trong chân trang THs.
Row Index và cell Index cung cấp vị trí chính xác của ô được nhấp.
Textcontent là văn bản của ô được nhấp.

Bằng cách này, tôi không cần truyền dữ liệu của tế bào cho người xử lý, nó có thể tự phục vụ nó.
Nếu tôi cần thêm dữ liệu, dữ liệu không được hiển thị, tôi có thể sử dụng thuộc tính bộ dữ liệu hoặc các yếu tố ẩn.
Với một số điều hướng DOM đơn giản, tất cả đều sẵn sàng.
Điều này đã được sử dụng trong HTML từ bao giờ, vì PC dễ sa lầy hơn nhiều.


0

Có một số cách để truyền tham số trong trình xử lý sự kiện, một số cách sau.

Bạn có thể sử dụng chức năng mũi tên để bọc xung quanh trình xử lý sự kiện và truyền tham số:

<button onClick={() => this.handleClick(id)} />

ví dụ trên tương đương với việc gọi .bindhoặc bạn có thể gọi ràng buộc một cách rõ ràng.

<button onClick={this.handleClick.bind(this, id)} />

Ngoài hai cách tiếp cận này, bạn cũng có thể truyền đối số cho một hàm được xác định là hàm cà ri.

handleClick = (id) => () => {
    console.log("Hello, your ticket number is", id)
};

<button onClick={this.handleClick(id)} />

-1

Sử dụng một đóng cửa , nó dẫn đến một giải pháp sạch:

<th onClick={this.handleSort(column)} >{column}</th>

Hàm handleSort sẽ trả về một hàm đã đặt cột giá trị .

handleSort: function(value) { 
    return () => {
        console.log(value);
    }
}

Hàm ẩn danh sẽ được gọi với giá trị chính xác khi người dùng nhấp vào th.

Ví dụ: https://stackblitz.com/edit/react-pass-parameter-example


-2

Thay đổi đơn giản là bắt buộc:

Sử dụng <th value={column} onClick={that.handleSort} >{column}</th>

thay vì <th value={column} onClick={that.handleSort} >{column}</th>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.