React js onClick nu poate trece valoarea la metodă (Programare, Javascript, Reactjs)

user1924375 a intrebat.

Vreau să citesc proprietățile valorii evenimentului onClick. Dar când fac clic pe el, văd ceva de genul acesta în consolă:

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

Codul meu funcționează corect. Când îl execut, pot vedea {column} dar nu o pot obține în evenimentul onClick.

Codul meu:

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

Cum pot să trec o valoare la onClick eveniment în React js?

Comentarii

  • posibil duplicat al legării evenimentului OnClick Event binding în React.js –  > Por WiredPrairie.
  • luați în considerare folosirea lui self în loc de asta. Acesta este destul de înșelător, deoarece ar trebui să fie sinonim cu „this” (nu este foarte important totuși, fiecare cu ce are) –  > Por Dan.
  • Folosind metoda bind și metoda arrow putem trece valoarea la evenimentul Onclick –  > Por Merugu Prashanth.
  • De acord cu @WiredPrairie și tipul numit ZenMaster a explicat precis și eficient. –  > Por perfectionist1.
33 răspunsuri
Austin Greco

Easy Way

Folosiți o funcție săgeată:

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

Aceasta va crea o nouă funcție care va apela handleSort cu parametrii corecți.

Cale mai bună

Extrageți-o într-un subcomponent.Problema cu utilizarea unei funcții săgeată în apelul de randare este că va crea o nouă funcție de fiecare dată, ceea ce sfârșește prin a provoca reluări inutile.

Dacă creați un subcomponent, puteți trece handler și folosi props ca argumente, care va reda doar atunci când props se schimbă (deoarece referința handlerului nu se schimbă niciodată):

Subcomponenta

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

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

Componenta principală

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

Vechea metodă simplă (ES5)

Utilizați .bind pentru a trece parametrul dorit; în acest fel, legați funcția de contextul componentei:

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

Comentarii

  • react dă un avertisment atunci când folosesc codul dumneavoastră. Îmi schimb codul în onClick={that.onClick.bind(null,column)}. –  > Por user1924375.
  • Cum ați putea utiliza acest lucru cu un <a> în cazul în care trebuie să treceți evenimentul, pentru a utiliza preventDefault() –  > Por Simon H.
  • 38

  • @SimonH Evenimentul va fi trecut ca ultim argument, după argumentele pe care le treceți prin bind. –  > Por smudge.
  • 47

  • Nu este acest lucru rău pentru performanță? nu va fi creată o nouă funcție la fiecare randare? –  > Por AndrewMcLagan.
  • @AndrewMcLagan Așa este. I am găsit asta pentru a descrie regula și soluția cea mai performantă. –  > Por E. Sundin.
Sagiv b.g

Există răspunsuri frumoase aici, și sunt de acord cu @Austin Greco (a doua opțiune cu componente separate)
Există o altă modalitate care îmi place, currying.
Ceea ce puteți face este să creați o funcție care acceptă un parametru (parametrul dvs.) și returnează o altă funcție care acceptă un alt parametru (evenimentul click în acest caz). apoi sunteți liber să faceți cu ea ce doriți.

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

Și o veți utiliza în acest mod:

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

Iată un exemplu complet de astfel de utilizare:

Rețineți că această abordare nu rezolvă problema creării unei noi instanțe la fiecare randare.
Îmi place această abordare față de ceilalți gestionari inline, deoarece, în opinia mea, aceasta este mai concisă și mai ușor de citit.

Editați:
Așa cum s-a sugerat în comentariile de mai jos, puteți să memorați / memoizați rezultatul funcției.

Iată o implementare naivă:

Comentarii

  • Acesta ar trebui să fie răspunsul acceptat. Foarte ușor de implementat și nu este nevoie să creați alte componente sau să faceți bind-uri diferite. Vă mulțumim! –  > Por Tamb.
  • 31

  • Arată mai bine, dar din punct de vedere al performanței, totuși, currying nu prea ajută, pentru că dacă apelați handleChange de două ori, cu același parametru, veți obține două funcții pe care motorul JS le consideră obiecte separate, chiar dacă fac același lucru. Deci, tot veți obține o redare. Din motive de performanță, ar trebui să puneți în cache rezultatele handleChange pentru a obține avantajul de performanță. Cum ar fi handleChange = param => cache[param] || (e => { // the function body }) –  > Por travellingprog.
  • Acesta este răspunsul perfect dacă îndepliniți sfatul lui @travellingprog –  > Por llioor.
  • Poate cineva să furnizeze un link sau să explice cum funcționează acest mecanism de cache ? mulțumesc. –  > Por Sadok Mtir.
  • Dacă folosiți currying, la fiecare randare va fi creată o nouă funcție. Aceeași problemă de performanță apare ca și trecerea unei funcții săgeată. –  > Por omeralper.
aikeru

În zilele noastre, cu ES6, cred că ne-ar prinde bine un răspuns actualizat.

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

Practic, (pentru cei care nu știu) de când cu onClick așteaptă o funcție care îi este transmisă, bind funcționează deoarece creează o copie a unei funcții. În schimb, putem trece o expresie de funcție săgeată care invocă pur și simplu funcția pe care o dorim și păstrează this. Niciodată nu ar trebui să fie nevoie să legați expresia render în React, dar dacă, din anumite motive, pierdeți this în una dintre metodele componentei dvs:

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

Comentarii

  • Nu trebuie niciodată să legați render() deoarece este apelată de React. În orice caz, trebuie să bind gestionarii de evenimente, și numai atunci când nu utilizați săgeți. –  > Por Dan Abramov.
  • @DanAbramov Cred că aveți dreptate, dar am inclus-o pentru orice eventualitate – actualizată cu un exemplu care nu încurajează implicit redarea obligatorie. –  > Por aikeru.
  • Rețineți că este, de asemenea, cel mai bine să treceți props la super() sau this.props va fi nedefinit în timpul constructorului, ceea ce poate deveni confuz. –  > Por Dan Abramov.
  • Pentru a realiza ce? Puteți defini un gestionar în interiorul componentei funcționale și îl puteți transmite. Aceasta va fi o funcție diferită la fiecare randare, astfel încât dacă ați stabilit cu ajutorul unui profiler că vă dă probleme de performanță. (și numai dacă sunteți sigur de acest lucru!), luați în considerare utilizarea unei clase în schimb. –  > Por Dan Abramov.
  • Mulțumesc Aikeru. Ah, bine, deci vrei să spui că dacă declari metoda foo ca o funcție săgeată în clasa însăși, apoi faci referire la ea folosind contextul this, atunci este creată o singură dată, în loc să o declari în interiorul onClick, unde se creează aceeași funcție de fiecare dată când faci clic pe buton. Este corectă gândirea mea? –  > Por me-me.
Brandon

[[h/t la @E.Sundin pentru linking this într-un comentariu]

Răspunsul de sus (funcții anonime sau legături) va funcționa, dar nu este cel mai performant, deoarece creează o copie a gestionarului de evenimente pentru fiecare instanță generată de către map() funcție.

Aceasta este o explicație a modului optim de a face acest lucru din ESLint-plugin-react:

Listă de elemente

Un caz de utilizare obișnuită a funcției bind in render este atunci când se redă o listă, pentru a avea un callback separat pentru fiecare element din listă:

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

În loc să faceți în acest mod, trageți secțiunea repetată în propria componentă:

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

});

Acest lucru va accelera redarea, deoarece se evită necesitatea de a crea funcții noi (prin apeluri bind) la fiecare redare.

Comentarii

  • Reaction invocă aceste funcții cu call/apply, atunci, sub capotă, și evită să folosească bind intern? –  > Por aikeru.
  • Există o modalitate de a face acest lucru folosind o componentă fără stat? –  > Por Carlos Martinez.
  • @CarlosMartinez ochi buni, am actualizat exemplul – ar fi trebuit să fie componente funcționale fără stat (SFC) în primul rând. În general, dacă o componentă nu folosește niciodată this.state, o puteți înlocui în siguranță cu o SFC. –  > Por Brandon.
  • Hmm, nu înțeleg de ce este mai performant? Funcția ListItem nu va fi invocată de fiecare dată și, prin urmare, funcția _onClick va fi creată la fiecare randare. –  > Por Mattias Petter Johansson.
  • Sunt departe de a fi un expert în domeniu, dar, din câte am înțeles, în modelul „corect”, există o singură instanță a gestionarului și i se transmite recuzita pentru orice instanță a componentei care îl apelează. În exemplul bind (adică, modelul „greșit”), există o instanță a gestionarului pentru fiecare componentă instanțiată. Este un fel de echivalent de memorie al scrierii aceleiași funcții de treizeci de ori, care se scrie o singură dată & apelând-o acolo unde este necesar. –  > Por Brandon.
Santiago Ramirez

Aceasta este abordarea mea, nu sunt sigur cât de proastă este, vă rog să comentați

În elementul pe care se poate face clic

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

și apoi

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

Comentarii

  • Aceasta este o abordare la care mă gândeam, se simte un pic hacky, dar evită crearea unei noi componente. Nu sunt sigur dacă getAttribute este mai bun sau mai rău din punct de vedere al perfomanței în comparație cu tragerea într-o componentă separată. –  > Por kamranicus.
  • Cred că este o soluție bună, deoarece este foarte simplă. Dar funcționează numai cu valori de tip șir de caractere, dacă doriți un obiect nu funcționează. –  > Por Stephane L.
  • Pentru un obiect ar trebui să faceți encodeURIComponent(JSON.stringify(myObj)), , apoi să îl analizați, JSON.parse(decodeURIComponent(myObj)). Pentru funcții sunt destul de sigur că nu va funcționa fără eval sau new Function(), ambele ar trebui evitate. Din aceste motive, nu folosesc data-attributes pentru a trece date în React/JS. –  > Por png.
  • Vreau să adaug că nu folosesc acest lucru des și doar pentru lucruri minore. Dar, de obicei, creez doar o componentă și îi trec datele ca props. Apoi, fie gestionez click-ul în interiorul acelei noi componente, fie trec o funcție onClick către componentă. Așa cum este explicat în răspunsul lui Brandon –  > Por Santiago Ramirez.
  • setul de date poate fi accesat direct în acest mod pe browserele moderne (inclusiv IE11): e.currentTarget.dataset.column –  > Por gsziszi.
hannad rehman

acest exemplu ar putea fi puțin diferit de al tău. dar te pot asigura că aceasta este cea mai bună soluție pe care o poți avea pentru această problemă. am căutat zile întregi o soluție care să nu aibă probleme de performanță. și în cele din urmă am găsit-o pe aceasta.

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

UPDATE

în cazul în care doriți să vă ocupați de obiecte care ar trebui să fie parametrii, puteți utiliza JSON.stringify(object) pentru a le converti în șir de caractere și a le adăuga la setul de date.

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

Comentarii

  • acest lucru nu funcționează atunci când datele transmise sunt un obiect –  > Por SlimSim.
  • utilizați JSON.stringify pentru a rezolva problema. @SlimSim . asta ar trebui să rezolve problema –  > Por hannad rehman.
  • Dacă trebuie să folosiți JSON.stringify pentru această problemă, atunci probabil că nu este metoda corectă. Procesul de stringificare necesită multă memorie. –  > Por KFE.
  • în cele mai multe cazuri, veți trece doar ID-ul ca parametrii și veți obține detaliile obiectului pe baza acelui ID din obiectul sursă. și de ce și cum de necesită multă memorie, știu că JSON stringify este lent, dar Fn-ul de clic este asincron și nu va avea niciun efect sau 0 asupra domului, odată construit –  > Por hannad rehman.
Charith Jayasanka

Pur și simplu creați o funcție ca aceasta

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

și apelați-o în locul de care aveți nevoie

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

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

Comentarii

  • Același lucru – un nou DOM la fiecare randare. Astfel, React va actualiza DOM de fiecare dată. –  > Por Alex Shwarc.
jhchnc

Îmi dau seama că acest lucru este destul de târziu la petrecere, dar cred că o soluție mult mai simplă ar putea satisface multe cazuri de utilizare:

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

    ...

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

Presupun că ați putea folosi și un data- atribut.

Simplu, semantic.

Brett DeWoody

Încă o opțiune care nu implică .bind sau ES6 este de a utiliza o componentă copil cu un gestionar pentru a apela gestionarul părinte cu accesoriile necesare. Iată un exemplu (și un link către un exemplu funcțional este mai jos):

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

Ideea de bază este ca componenta părinte să treacă onClick către o componentă copil. Componenta copil apelează funcția onClick și poate accesa orice props care i-a fost transmisă (și event), ceea ce vă permite să utilizați orice event sau alte elemente de recuzită din cadrul componentei părinte. onClick a părintelui.

Iată un exemplu de demo CodePen care arată această metodă în acțiune.

Po Rith

Făcând o încercare alternativă de a răspunde la întrebarea lui OP, inclusiv apelurile e.preventDefault():

Link redat (ES6)

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

Funcție de componentă

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

Louis Alonzo

Puteți face acest lucru pur și simplu dacă utilizați 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>
     );
   }
 }

nandu

Implementarea afișării numărului total dintr-un obiect prin trecerea numărului ca parametru de la componentele principale la cele secundare, așa cum este descris mai jos.

Aici este 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;

Și aici este 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>
    )
  }
};

Încercați să implementați mai sus și veți obține scenariul exact că modul în care funcționează trecerea parametrilor în reactjs pe orice metodă DOM.

SlimSim

Am scris o componentă wrapper care poate fi reutilizată în acest scop și care se bazează pe răspunsurile acceptate aici. Dacă tot ce trebuie să faceți este să treceți totuși un șir de caractere, atunci adăugați un atribut de date și citiți-l din e.target.dataset (așa cum au sugerat alții). În mod implicit, wrapper-ul meu se va lega la orice prop care este o funcție și începe cu „on” și va transmite automat prop-ul de date înapoi la apelant după toate celelalte argumente ale evenimentului. Deși nu am testat-o pentru performanță, vă va oferi posibilitatea de a evita crearea clasei și poate fi utilizată astfel:

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

sau pentru Componente și funcții

const DataInput = withData(SomeComponent);

sau, dacă preferați

const DataButton = withData(<button/>)

declarați că În afara containerului dvs. (lângă importuri)

Iată utilizarea într-un 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>
        );
    }
}

Iată codul de înfășurare ‘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;
    }, {});
}

Reetesh Agrawal

Am mai jos 3 sugestii pentru acest lucru pe JSX onClick Events –

  1. De fapt, nu este nevoie să folosim funcția .bind() sau Arrow în codul nostru. Puteți utiliza simplu în codul dvs.

  2. De asemenea, puteți muta evenimentul onClick de la th(sau ul) la tr(sau li) pentru a îmbunătăți performanța. Practic, veți avea un număr n de „Ascultători de evenimente” pentru elementul n li.

    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>
    

    // Și puteți accesa item.id în onItemClick așa cum se arată mai jos:

    onItemClick = (event) => {
       console.log(e.target.getAttribute("item.id"));
    }
    
  3. Sunt de acord cu abordarea menționată mai sus pentru crearea unei componente React separate pentru ListItem și List. Acest cod arată bine, dar dacă aveți 1000 de li, atunci vor fi create 1000 de ascultători de evenimente. Vă rugăm să vă asigurați că nu ar trebui să aveți prea mulți ascultători de evenimente.

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

Comentarii

  • Acest lucru nu funcționează atunci când datele pe care trebuie să le transmiteți sunt un obiect. Atributul va funcționa numai cu șiruri de caractere. De asemenea, citirea din dom prin atributul get este probabil o operațiune mai costisitoare. –  > Por SlimSim.
Merugu Prashanth

Am adăugat codul pentru trecerea valorii evenimentului onclick la metoda în două moduri . 1 . folosind metoda bind 2. folosind metoda arrow(=>) . vezi metodele handlesort1 și 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>);
    }
});

Karan Singh

Mai jos este exemplul care trece valoarea la evenimentul onClick.

Am folosit sintaxa es6. Amintiți-vă că în componenta de clasă, funcția arrow nu se leagă automat, deci se leagă explicit în constructor.

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

Andysenclave

Cred că va trebui să legați metoda de instanța clasei React. Este mai sigur să folosiți un constructor pentru a lega toate metodele din React. În cazul dvs. atunci când treceți parametrul în metodă, primul parametru este utilizat pentru a lega contextul „this” al metodei, astfel încât nu puteți accesa valoarea în interiorul metodei.

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

Romia Mukherjee

Theres’ o modalitate foarte ușoară.

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

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

Comentarii

  • Deși acest cod poate rezolva întrebarea, incluzând o explicație ajută cu adevărat la îmbunătățirea calității postării dvs. Nu uitați că răspundeți la întrebare pentru cititorii din viitor, iar acei oameni ar putea să nu cunoască motivele pentru sugestia dvs. de cod. –  > Por Shree.
Charitha Goonewardena

Ieșind de nicăieri la această întrebare, dar cred că .bind va fi de ajuns. Găsiți codul de probă de mai jos.

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

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

Umair Ahmed

Există câteva moduri de a trece parametrii în gestionarii de evenimente, unele sunt următoarele.

Puteți utiliza o funcție de săgeată pentru a înfășura un gestionar de eveniment și a trece parametrii:

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

exemplul de mai sus este echivalent cu apelarea .bind sau puteți apela explicit bind.

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

În afară de aceste două abordări, puteți, de asemenea, să transmiteți argumente unei funcții definite ca o funcție curry.

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

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

SM Chinna

Utilizarea funcției săgeată :

Trebuie să instalați stage-2:

npm install 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; 

Mansi Teharia

Există 3 moduri de a gestiona acest lucru :-

  1. Legați metoda în constructor ca :-

    export class HeaderRows extends Component {
       constructor() {
           super();
           this.handleSort = this.handleSort.bind(this);
       }
    }
    
  2. Utilizați funcția săgeată în timpul creării ca :-

    handleSort = () => {
        // some text here
    }
    
  3. A treia modalitate este următoarea :-

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

Bankim Sutaria

Puteți utiliza codul dvs. astfel:

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

Aici e este pentru obiect de eveniment, dacă doriți să utilizați metode de eveniment precum preventDefault() în funcția de manipulare sau dacă doriți să obțineți valoarea sau numele obiectivului, cum ar fi e.target.name.

sneas

Soluția de a trece param ca atribut al unei etichete mi s-a părut destul de rezonabilă.

Cu toate acestea, ea are limitări:

  • Nu funcționează corect atunci când elementul din listă are alte etichete (astfel, event.target ar putea fi diferit de cel dorit).
  • Param poate fi doar un șir de caractere. Necesită serializare și deserializare.

De aceea am venit cu această bibliotecă: react-event-param

It:

  • Rezolvă problema copiilor prin căutarea atributului necesar în părinți ori de câte ori este nevoie
  • Serializează și deserializează automat parametrii
  • Încapsulează logica de setare și de obținere. Nu este nevoie să vă încurcați cu numele parametrilor

Exemplu de utilizare:

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;

Juan Lanus

Au existat o mulțime de considerente de performanță, toate în vid.
Problema cu acești handlers este că trebuie să îi curățiți pentru a încorpora argumentul pe care nu îl puteți numi în props.
Acest lucru înseamnă că componenta are nevoie de un handler pentru fiecare element pe care se poate face clic. Să fim de acord că pentru câteva butoane acest lucru nu este o problemă, nu?
Problema apare atunci când manipulați date tabelare cu zeci de coloane și mii de rânduri. Acolo observați impactul creării unui număr atât de mare de gestionari.

Adevărul este că nu am nevoie decât de unul singur.
Am setat gestionarul la nivelul tabelului (sau UL sau OL…), iar când se produce clicul pot spune care a fost celula pe care s-a făcut clic folosind datele disponibile dintotdeauna în obiectul evenimentului:

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

Folosesc câmpurile tagname pentru a verifica dacă clicul s-a produs într-un element valid, de exemplu, ignor clicurile din TH sau footer.
RowIndex și cellIndex oferă locația exactă a celulei pe care s-a făcut clic.
Textcontent este textul celulei pe care s-a făcut clic.

În acest fel, nu este nevoie să transmit datele celulei către handler, acesta se poate autoservi.
Dacă aș avea nevoie de mai multe date, date care nu trebuie afișate, pot folosi atributul dataset sau elemente ascunse.
Cu o simplă navigare DOM, totul este la îndemână.
Acest lucru a fost folosit în HTML dintotdeauna, de când PC-urile erau mult mai ușor de împotmolit.

Comentarii

  • Ați ridicat o problemă foarte importantă – luarea în considerare a performanței! –  > Por perfecționist1.
Marcus Melodious

Cea mai bună soluție cu React >= 16

Cea mai curată modalitate pe care am găsit-o pentru a apela funcții cu mai mulți parametri în onClick, onChange etc., fără a utiliza funcții inline, este de a utiliza funcția personalizată data atribut disponibil în React 16 și în versiunile ulterioare.

const App = () => {
  const onClick = (e) => {
    const value1 = e.currentTarget.getAttribute("data-value1")
    const value2 = e.currentTarget.getAttribute("data-value2")
    const value2 = e.currentTarget.getAttribute("data-value2")
    console.log("Values1", value1)
    console.log("Values2", value2)
    console.log("Values3", value3)
  }
  return (
    <button onClick={onClick} data-value1="a" data-value2="b" data-value3="c" />
  )
}

Exemplul de mai sus este pentru o componentă funcțională, dar implementarea este destul de similară chiar și în cazul componentelor de clasă.

Această abordare nu generează redistribuiri inutile, deoarece nu folosiți funcții inline și evitați complicațiile legate de legarea cu this.

Aceasta vă permite să treceți oricâte valori doriți să utilizați în funcție.

Dacă transmiteți valori ca elemente de recuzită copiilor dvs. pentru a fi utilizate în onClick al componentei copil, puteți utiliza această abordare și acolo, fără a crea o funcție de înfășurare.

Funcționează și cu array-uri de obiecte, în cazurile în care doriți să treceți id-ul de la obiect la funcția onClick, , așa cum se arată mai jos.

const App = () => {
  const [arrState, setArrState] = useState(arr)

  const deleteContent = (e) => {
    const id = e.currentTarget.getAttribute("data-id")
    const tempArr = [...arrState]
    const filteredArr = tempArr.filter((item) => item.id !== id)
    setArrState(filteredArr)
  }

  return (
    <div>
      {arrState.map((item) => (
        <React.Fragment key={item.id}>
          <p>{item.content}</p>
          <button onClick={deleteContent} data-id={item.id}>
            Delete
          </button>
        </React.Fragment>
      ))}
    </div>
  )
}

Ganesh Koilada

Trebuie doar să folosiți funcția Arrow pentru a trece valoarea.

<button onClick={() => this.props.onClickHandle("StackOverFlow")}>

Asigurați-vă că utilizați () = >, În caz contrar, metoda click va fi apelată fără evenimentul click.

Notă : Crash verifică metodele implicite

Vă rugăm să găsiți mai jos codul de funcționare în codesandbox pentru același lucru.

React trece valoarea cu metoda

Al Amin Shaon

Este necesară o modificare simplă:

Utilizați <th value={column} onClick={that.handleSort} >{column}</th>

în loc de<th value={column} onClick={that.handleSort} >{column}</th>

Romel Gomez

Utilizați un închidere, , rezultă o soluție curată:

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

funcția handleSort va returna o funcție care are valoarea coloana deja setată.

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

Funcția anonimă va fi apelată cu valoarea corectă atunci când utilizatorul va face clic pe th.

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

MiF

Cred că, .bind(this, arg1, arg2, ...) în harta React – este un cod prost, pentru că este lent! 10-50 de .bind(this) într-o singură metodă de randare – cod foarte lent.
Eu îl rezolv așa:
Metoda de randare
<tbody onClick={this.handleClickRow}>
map of <tr data-id={listItem.id}>
Handler
var id = $(ev.target).closest('tr').data().id

Codul complet de mai jos:

Comentarii

  • Vă rugăm să scrieți comentarii pentru ceea ce vă lipsește –  > Por MiF.
  • Amestecarea JQuery cu React nu este o modalitate recomandată de a folosi React, mai ales dacă testați codul în mod unitar. Răspunsul cel mai idiomatic este să separați elementele din lista dvs. în componente copil, deoarece acestea au acțiuni care probabil afectează starea aplicației. –  > Por kamranicus.
  • Știu, dar este doar pentru cea mai simplă demonstrație a soluției mele. –  > Por MiF.
  • În codul dvs., jQuery face mai mult decât să vă demonstreze soluția. Pentru gestionarii de pe <tr> însuși, puteți să omiteți closest și nu aveți nevoie de niciun jQuery, astfel încât soluția dvs. este la fel ca și altele care folosesc data-*. Pentru gestionarii de pe componentele din interiorul componentelor <tr>, , aveți nevoie de unele manipulări DOM… ceea ce nu este bine, după cum s-a spus deja, dar astfel de gestionari nu au fost solicitați. –  > Por maaartinus.
  • Aveți dreptate. Acum cred că cea mai bună cale este să creăm o componentă imbricata și să o returnăm din funcția map. În acest fel, nu mai trebuie să lucrați cu DOM, iar crearea unei componente imbricate cu bindings se va face o singură dată. –  > Por MiF.