Bereaksi js onClick tidak bisa meneruskan nilai ke metode

639

Saya ingin membaca properti nilai event onClick. Tetapi ketika saya mengkliknya, saya melihat sesuatu seperti ini di konsol:

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

Kode saya berfungsi dengan benar. Ketika saya menjalankan saya bisa melihat {column}tetapi tidak bisa mendapatkannya di acara onClick.

Kode Saya:

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>
    );
  }
});

Bagaimana saya bisa meneruskan nilai ke onClickacara di Bereaksi js?

pengguna1924375
sumber
2
kemungkinan duplikat dari Peristiwa OnClick yang mengikat di React.js
WiredPrairie
2
pertimbangkan untuk menggunakan diri sendiri, bukan itu. Itu cukup menyesatkan karena harus identik dengan "ini" (sebenarnya tidak terlalu penting, untuk masing-masing miliknya)
Dan
Menggunakan metode bind dan metode panah, kita dapat meneruskan nilainya ke acara
Onclick
1
lihat contoh ini Melewati parameter ke fungsi panah di bereaksi js
sumit kumar pradhan

Jawaban:

1287

Jalan mudah

Gunakan fungsi panah:

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

Ini akan membuat fungsi baru yang memanggil handleSortdengan params yang tepat.

Cara yang lebih baik

Ekstrak itu menjadi sub-komponen. Masalah dengan menggunakan fungsi panah dalam panggilan render adalah ia akan membuat fungsi baru setiap kali, yang akhirnya menyebabkan rendering ulang yang tidak dibutuhkan.

Jika Anda membuat sub-komponen, Anda bisa meneruskan handler dan menggunakan props sebagai argumen, yang kemudian akan merender ulang hanya ketika props berubah (karena referensi handler sekarang tidak pernah berubah):

Sub-komponen

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

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

Komponen utama

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

Old Easy Way (ES5)

Gunakan .binduntuk melewatkan parameter yang Anda inginkan:

return (
  <th value={column} onClick={that.handleSort.bind(that, column)}>{column}</th>
);
Austin Greco
sumber
7
Reaksi memberi peringatan ketika saya menggunakan seperti kode Anda. Saya mengubah kode saya ke onClick = {that.onClick.bind (null, kolom)}
user1924375
12
Bagaimana Anda menggunakan ini dengan <a>tag di mana Anda harus melewati acara tersebut, agar dapat menggunakanpreventDefault()
Simon H
38
@SimonH Acara ini akan diteruskan sebagai argumen terakhir, setelah argumen yang Anda sampaikan bind.
noda
47
Apakah ini tidak buruk untuk kinerja? tidak akankah fungsi baru dibuat pada setiap render?
AndrewMcLagan
13
@AndrewMcLagan Ini. Saya menemukan ini untuk menggambarkan aturan dan solusi yang paling berkinerja.
E. Sundin
140

Ada jawaban yang bagus di sini, dan saya setuju dengan @Austin Greco (opsi kedua dengan komponen terpisah)
Ada cara lain yang saya suka, kari .
Yang dapat Anda lakukan adalah membuat fungsi yang menerima parameter (parameter Anda) dan mengembalikan fungsi lain yang menerima parameter lain (acara klik dalam kasus ini). maka Anda bebas untuk melakukannya dengan apa pun yang Anda inginkan.

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
};

Dan Anda akan menggunakannya dengan cara ini:

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

Berikut ini adalah contoh lengkap dari penggunaan tersebut:

Perhatikan bahwa pendekatan ini tidak menyelesaikan pembuatan instance baru pada setiap render.
Saya suka pendekatan ini daripada penangan inline lainnya karena yang ini lebih ringkas dan mudah dibaca menurut pendapat saya.

Sunting:
Seperti yang disarankan dalam komentar di bawah ini, Anda dapat menyimpan / mem-memo hasil dari fungsi tersebut.

Berikut ini adalah implementasi yang naif:

Sagiv bg
sumber
12
Ini harus menjadi jawaban yang diterima. BENAR-BENAR mudah diimplementasikan dan Anda tidak perlu membuat komponen lain atau mengikat secara berbeda. Terima kasih!
Tamb
29
Terlihat lebih baik, tetapi dari perspektif kinerja, currying tidak terlalu membantu, karena jika Anda memanggil handleChange dua kali, dengan param yang sama, Anda mendapatkan dua fungsi yang dianggap oleh mesin JS sebagai objek yang terpisah, bahkan jika mereka melakukan hal yang sama . Jadi Anda masih mendapatkan render ulang. Demi kinerja, Anda perlu melakukan cache hasil handleChange untuk mendapatkan keuntungan kinerja. SepertihandleChange = param => cache[param] || (e => { // the function body })
travellingprog
6
Ini adalah jawaban yang sempurna jika Anda memenuhi saran dari @travellingprog
llioor
2
Adakah yang bisa memberikan tautan atau menjelaskan cara kerja mekanisme cache ini? Terima kasih.
Sadok Mtir
2
Cantik dan rapi!
Hatem Alimam
117

Saat ini, dengan ES6, saya merasa kami bisa menggunakan jawaban yang diperbarui.

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

Pada dasarnya, (untuk apa pun yang tidak tahu) karena onClickmengharapkan fungsi yang diteruskan ke sana, bindberfungsi karena ia membuat salinan fungsi. Sebagai gantinya, kita dapat meneruskan ekspresi fungsi panah yang hanya memanggil fungsi yang kita inginkan, dan mempertahankannya this. Anda seharusnya tidak perlu mengikat rendermetode dalam Bereaksi, tetapi jika karena alasan tertentu Anda kehilangan thissalah satu metode komponen Anda:

constructor(props) {
  super(props);
  this.myMethod = this.myMethod.bind(this);
}
aikeru
sumber
10
Anda tidak perlu mengikat render()karena ini disebut oleh Bereaksi. Jika ada, Anda harus ke bindpenangan acara, dan hanya ketika Anda tidak menggunakan panah.
Dan Abramov
1
@DanAbramov Saya pikir Anda benar, tapi saya memasukkannya untuk berjaga-jaga - diperbarui dengan contoh yang tidak secara implisit mendorong pengikatan render.
aikeru
3
Catatan itu juga terbaik untuk lulus propske super()atau this.propsakan terdefinisi selama konstruktor yang bisa membingungkan.
Dan Abramov
2
Untuk mencapai apa? Anda dapat mendefinisikan handler di dalam komponen fungsional dan meneruskannya. Ini akan menjadi fungsi yang berbeda setiap render jadi jika Anda telah menentukan dengan profiler bahwa itu memberi Anda masalah perf (dan hanya jika Anda benar-benar yakin dengan ini!), Pertimbangkan menggunakan kelas sebagai gantinya.
Dan Abramov
1
@ me-me Ya, dan jika Anda memilih ikut serta dalam JavaScript tepi di Babel, Anda harus mendeklarasikan properti di kelas Anda foo = () => {...}dan kemudian merujuk pada render <button onClick={this.foo}...satu-satunya alasan untuk menyertakan fungsi panah jika Anda menggunakan babel dengan cara ini, IMO, adalah jika Anda ingin menangkap beberapa variabel yang hanya ada dalam ruang lingkup metode render () (peristiwa bisa saja diteruskan dan tidak berlaku).
aikeru
73

[[h / t ke @ E.Sundin karena menautkan ini dalam komentar]

Jawaban teratas (fungsi anonim atau mengikat) akan berfungsi, tetapi bukan yang paling berkinerja, karena ia membuat salinan pengendali acara untuk setiap instance yang dihasilkan oleh map()fungsi.

Ini adalah penjelasan tentang cara optimal untuk melakukannya dari ESLint-plugin-react :

Daftar Item

Kasus umum yang digunakan dari bind in render adalah ketika merender daftar, untuk memiliki callback terpisah per item daftar:

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

Daripada melakukannya dengan cara ini, tarik bagian yang diulang ke dalam komponennya sendiri:

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>
    );

});

Ini akan mempercepat rendering, karena menghindari kebutuhan untuk membuat fungsi baru (melalui panggilan bind) pada setiap render.

Brandon
sumber
Apakah reaksi memanggil fungsi-fungsi itu dengan panggilan / menerapkan, kemudian, di bawah kap, dan menghindari penggunaan bind secara internal?
aikeru
1
Apakah ada cara untuk melakukan ini menggunakan komponen stateless?
Carlos Martinez
2
@CarlosMartinez mata yang baik, saya memperbarui contoh - mereka seharusnya komponen fungsional stateless (SFC) di tempat pertama. Secara umum, jika suatu komponen tidak pernah digunakan this.state, Anda dapat dengan aman menukar dengan SFC.
Brandon
3
Hmm, saya tidak mengerti bagaimana ini lebih performant? Bukankah fungsi ListItem dipanggil setiap waktu, dan dengan demikian fungsi _onClick akan dibuat setiap render.
Mattias Petter Johansson
1
Saya jauh dari ahli di sini, tetapi seperti yang saya pahami, dalam pola 'benar', hanya ada satu instance dari handler dan telah melewati prop untuk instance komponen mana pun yang menyebutnya. Dalam contoh binding (yaitu, pola 'salah'), ada satu instance dari handler untuk setiap komponen instantiated. Ini semacam memori yang setara dengan menulis fungsi yang sama tiga puluh kali wakil menulisnya sekali & menyebutnya di mana diperlukan.
Brandon
25

Ini pendekatan saya, tidak yakin seberapa buruk itu, silakan komentar

Dalam elemen yang dapat diklik

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

lalu

handleSort(e){
    this.sortOn(e.currentTarget.getAttribute('data-column'));
}
Santiago Ramirez
sumber
Ini adalah pendekatan yang saya pikirkan, rasanya agak berantakan tetapi menghindari membuat komponen baru. Saya tidak yakin apakah getAttribute lebih baik atau lebih buruk daripada menarik ke komponen yang terpisah.
kamranicus
2
Saya pikir ini solusi yang baik karena sangat sederhana. Tapi itu hanya berfungsi dengan nilai string, jika Anda menginginkan objek itu tidak berfungsi.
Stephane L
Untuk objek yang perlu Anda lakukan encodeURIComponent(JSON.stringify(myObj)), maka untuk menguraikannya JSON.parse(decodeURIComponent(myObj)),. Untuk fungsi, saya cukup yakin ini tidak akan berfungsi tanpa eval atau Function () baru, yang keduanya harus dihindari. Untuk alasan ini saya tidak menggunakan atribut data untuk meneruskan data di Bereaksi / JS.
Solvitieg
Saya ingin menambahkan saya tidak sering menggunakan ini dan hanya untuk hal-hal kecil. Tapi biasanya saya hanya membuat komponen dan meneruskan data sebagai alat bantu untuk itu. Kemudian baik menangani klik di dalam komponen baru itu atau meneruskan fungsi onClick ke komponen. Seperti dijelaskan dalam jawaban Brandon
Santiago Ramirez
1
dataset dapat diakses langsung dengan cara ini di browser modern (termasuk IE11): e.currentTarget.dataset.column
gsziszi
17

contoh ini mungkin sedikit berbeda dari milik Anda. tetapi saya dapat meyakinkan Anda bahwa ini adalah solusi terbaik yang dapat Anda miliki untuk masalah ini. Saya telah mencari solusi untuk hari yang tidak memiliki masalah kinerja. dan akhirnya muncul dengan yang satu ini.

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>
    );
  }
}

MEMPERBARUI

memetikan Anda ingin berurusan dengan objek yang seharusnya menjadi parameter. Anda dapat menggunakannya JSON.stringify(object)untuk mengonversinya menjadi string dan menambahkan ke kumpulan data.

return (
   <div>
     <h3 data-param={JSON.stringify({name:'me'})} onClick={this.handleClick}>
        {this.state.name}
     </h3>
   </div>
);
hannad rehman
sumber
1
ini tidak berfungsi ketika data yang dikirimkan adalah objek
SlimSim
gunakan JSON.stringify untuk memperbaiki masalah ini. @SlimSim. yang seharusnya melakukan trik
hannad rehman
Jika Anda perlu menggunakan JSON.stringify untuk masalah ini, maka itu mungkin bukan metode yang benar. Proses pengetatan membutuhkan banyak memori.
KFE
dalam sebagian besar kasus Anda hanya akan melewati ID sebagai params, dan mendapatkan detail objek berdasarkan ID itu dari objek sumber Anda. dan mengapa dan bagaimana cara mengambil banyak memori, saya tahu JSON merangkai lambat, tetapi klik Fn async dan itu tidak akan memiliki atau 0 efek pada dom, setelah dibangun
hannad rehman
6
class extends React.Component {
    onClickDiv = (column) => {
        // do stuff
    }
    render() {
        return <div onClick={() => this.onClickDiv('123')} />
    }
}
Vladimirs Matusevics
sumber
2
Yang sama - DOM baru pada setiap render. Jadi Bereaksi akan memperbarui DOM setiap kali.
Alex Shwarc
4

Satu lagi opsi yang tidak melibatkan .bindatau ES6 adalah menggunakan komponen anak dengan penangan untuk memanggil penangan induk dengan alat peraga yang diperlukan. Berikut ini contoh (dan tautan ke contoh kerja di bawah):

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);
    }
  }
});

Ide dasarnya adalah untuk komponen induk untuk meneruskan onClickfungsi ke komponen anak. Komponen anak memanggil onClickfungsi dan dapat mengakses setiap yang propsditeruskan ke sana (dan event), memungkinkan Anda untuk menggunakan eventnilai atau alat peraga lainnya dalam fungsi orangtua onClick.

Berikut ini demo CodePen yang menunjukkan metode ini dalam aksi.

Brett DeWoody
sumber
4

Melakukan upaya alternatif untuk menjawab pertanyaan OP termasuk panggilan e.preventDefault ():

Tautan yang dirender ( ES6 )

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

Fungsi Komponen

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

Saya menyadari ini cukup terlambat untuk pesta, tetapi saya pikir solusi yang lebih sederhana bisa memuaskan banyak kasus penggunaan:

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

    ...

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

Saya kira Anda juga bisa menggunakan data-atribut.

Sederhana, semantik.

jhchnc
sumber
4

Cukup buat fungsi seperti ini

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

dan menyebutnya di tempat yang Anda butuhkan

<Ikon onClick = {() => {methodName (theParamsYouwantToPass); }} />

Charith Jayasanka
sumber
3

Anda bisa melakukannya jika sedang menggunakan 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>
     );
   }
 }
Louis Alonzo
sumber
3

Implementing menunjukkan jumlah total dari suatu objek dengan melewatkan jumlah sebagai parameter dari utama ke sub komponen seperti yang dijelaskan di bawah ini.

Inilah 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;

Dan ini dia 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>
    )
  }
};

Cobalah untuk menerapkan di atas dan Anda akan mendapatkan skenario yang tepat bahwa cara melewatkan parameter bekerja di reactjs pada metode DOM apa pun.

nandu
sumber
3

Saya menulis komponen pembungkus yang dapat digunakan kembali untuk tujuan ini yang dibangun berdasarkan jawaban yang diterima di sini. Jika semua yang perlu Anda lakukan adalah meneruskan sebuah string, maka tambahkan saja atribut data dan bacalah dari e.target.dataset (seperti yang disarankan beberapa orang lain). Secara default pembungkus saya akan mengikat ke prop apa pun yang merupakan fungsi dan dimulai dengan 'on' dan secara otomatis meneruskan prop data kembali ke pemanggil setelah semua argumen acara lainnya. Meskipun saya belum mengujinya untuk kinerja, itu akan memberi Anda kesempatan untuk menghindari membuat kelas sendiri, dan itu dapat digunakan seperti ini:

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

atau untuk Komponen dan fungsi

const DataInput = withData(SomeComponent);

atau jika Anda suka

const DataButton = withData(<button/>)

nyatakan bahwa Di luar wadah Anda (dekat impor Anda)

Berikut ini adalah penggunaan dalam wadah:

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>
        );
    }
}

Ini adalah kode wrapper '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;
    }, {});
}
SlimSim
sumber
2

Saya memiliki saran di bawah 3 untuk ini di JSX onClick Events -

  1. Sebenarnya, kita tidak perlu menggunakan fungsi .bind () atau Arrow dalam kode kita. Anda dapat menggunakan sederhana dalam kode Anda.

  2. Anda juga dapat memindahkan onClick event dari th (atau ul) ke tr (atau li) untuk meningkatkan kinerja. Pada dasarnya Anda akan memiliki sejumlah "Pendengar Acara" untuk elemen Anda.

    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>

    // Dan Anda dapat mengakses item.iddalam onItemClickmetode seperti yang ditunjukkan di bawah ini:

    onItemClick = (event) => {
       console.log(e.target.getAttribute("item.id"));
    }
  3. Saya setuju dengan pendekatan yang disebutkan di atas untuk membuat Komponen Bereaksi terpisah untuk ListItem dan Daftar. Akan tetapi, kode ini terlihat bagus jika Anda memiliki 1000 li, maka 1000 Pendengar Acara akan dibuat. Pastikan Anda tidak memiliki banyak pendengar acara.

    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>
            );
        }
    }
Reetesh Agrawal
sumber
1
Ini tidak berfungsi ketika data yang Anda perlukan untuk lulus adalah objek. Atribut hanya akan bekerja dengan string. Juga membaca dari dom melalui atribut get mungkin operasi yang lebih mahal.
SlimSim
2

Saya telah menambahkan kode untuk nilai event onclick yang diteruskan ke metode dengan dua cara. 1. menggunakan metode bind 2. menggunakan metode panah (=>). lihat metode handlesort1 dan handlesort

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>);
    }
});
Prashanth Merugu
sumber
2

Di bawah ini adalah contoh yang meneruskan nilai pada acara onClick.

Saya menggunakan sintaks es6. ingat di komponen panah fungsi kelas tidak mengikat secara otomatis, jadi secara eksplisit mengikat konstruktor.

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>
         );
    }
}
Karan Singh
sumber
2

Saya kira Anda harus mengikat metode ke instance kelas React. Lebih aman menggunakan konstruktor untuk mengikat semua metode dalam Bereaksi. Dalam kasus Anda ketika Anda meneruskan parameter ke metode, parameter pertama digunakan untuk mengikat konteks 'ini' metode, sehingga Anda tidak dapat mengakses nilai di dalam metode.

Andysenclave
sumber
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);
}
Juan David Arce
sumber
2

Ada cara yang sangat mudah.

 onClick={this.toggleStart('xyz')} . 
  toggleStart= (data) => (e) =>{
     console.log('value is'+data);  
 }
Roma Mukherjee
sumber
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>
    );
  }
}
Anik Mazumder
sumber
4
Sementara kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, dan orang-orang itu mungkin tidak tahu alasan untuk saran kode Anda.
Shree
2

Datang entah dari mana ke pertanyaan ini, tetapi saya pikir .bindakan melakukan trik. Temukan kode contoh di bawah ini.

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

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

Menggunakan fungsi panah:

Anda harus menginstal tahap-2:

npm instal babel-preset-stage-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; 
SM Chinna
sumber
0

Ada 3 cara untuk menangani ini: -

  1. Bind metode dalam konstruktor sebagai: -

    export class HeaderRows extends Component {
       constructor() {
           super();
           this.handleSort = this.handleSort.bind(this);
       }
    }
  2. Gunakan fungsi panah saat membuatnya sebagai: -

    handleSort = () => {
        // some text here
    }
  3. Cara ketiga adalah ini: -

    <th value={column} onClick={() => that.handleSort} >{column}</th>
Mansi Teharia
sumber
0

Anda dapat menggunakan kode Anda seperti ini:

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

Di sini e adalah untuk objek acara, jika Anda ingin menggunakan metode acara seperti preventDefault()pada fungsi pegangan Anda atau ingin mendapatkan nilai target atau nama seperti e.target.name.

Bankim Sutaria
sumber
0

Saya menemukan solusi melewati param sebagai atribut tag cukup masuk akal.

Namun memiliki keterbatasan:

  • Tidak berfungsi dengan baik ketika item daftar memiliki tag lain (sehingga event.target mungkin berbeda dengan yang dimaksudkan)
  • Param bisa berupa string saja. Membutuhkan serialisasi dan deserialisasi.

Itu sebabnya saya datang dengan perpustakaan ini: react-event-param

Itu:

  • Memecahkan masalah anak-anak dengan mencari atribut yang diperlukan pada orang tua kapan pun dibutuhkan
  • Membuat serialisasi dan deserialisasi param secara otomatis
  • Merangkum logika pengaturan dan mendapatkan. Tidak perlu dipusingkan dengan nama param

Contoh penggunaan:

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;
snea
sumber
0

Ada banyak pertimbangan kinerja, semuanya dalam ruang hampa.
Masalah dengan penangan ini adalah bahwa Anda perlu menjilat mereka untuk memasukkan argumen yang tidak dapat Anda sebutkan dalam props.
Ini berarti bahwa komponen membutuhkan penangan untuk setiap elemen yang dapat diklik. Mari kita sepakat bahwa untuk beberapa tombol ini bukan masalah, kan?
Masalah muncul ketika Anda menangani data tabular dengan puluhan kolom dan ribuan baris. Di sana Anda melihat dampak menciptakan banyak penangan.

Faktanya, saya hanya butuh satu.
Saya mengatur handler di level tabel (atau UL atau OL ...), dan ketika klik terjadi, saya dapat mengetahui sel mana yang diklik menggunakan data yang tersedia sejak di objek acara:

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

Saya menggunakan bidang tagname untuk memeriksa bahwa klik terjadi pada elemen yang valid, misalnya mengabaikan klik di THs ot footer.
RowIndex dan cellIndex memberikan lokasi yang tepat dari sel yang diklik.
Isi teks adalah teks dari sel yang diklik.

Dengan cara ini saya tidak perlu meneruskan data sel ke pawang, itu bisa swalayan.
Jika saya membutuhkan lebih banyak data, data yang tidak dapat ditampilkan, saya dapat menggunakan atribut dataset, atau elemen tersembunyi.
Dengan beberapa navigasi DOM sederhana semuanya ada di tangan.
Ini telah digunakan dalam HTML sejak itu, karena PC jauh lebih mudah untuk rawa.

Juan Lanus
sumber
0

Ada beberapa cara untuk melewatkan parameter di penangan acara, beberapa mengikuti.

Anda dapat menggunakan fungsi panah untuk membungkus pengatur kejadian dan meneruskan parameter:

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

contoh di atas setara dengan panggilan .bindatau Anda dapat secara eksplisit memanggil bind.

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

Terlepas dari dua pendekatan ini, Anda juga bisa meneruskan argumen ke fungsi yang didefinisikan sebagai fungsi kari.

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

<button onClick={this.handleClick(id)} />
Umair Ahmed
sumber
-1

Gunakan penutup , itu menghasilkan solusi bersih:

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

Fungsi handleSort akan mengembalikan fungsi yang sudah ditetapkan kolom nilai .

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

Fungsi anonim akan dipanggil dengan nilai yang benar ketika pengguna mengklik th.

Contoh: https://stackblitz.com/edit/react-pass-parameters-example

Romel Gomez
sumber
-2

Diperlukan perubahan sederhana:

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

dari pada <th value={column} onClick={that.handleSort} >{column}</th>

Al Amin Shaon
sumber