React js onClick विधि को मान नहीं दे सकता है


638

मैं ऑनक्लिक इवेंट वैल्यू प्रॉपर्टीज पढ़ना चाहता हूं। लेकिन जब मैं उस पर क्लिक करता हूं, तो मुझे कंसोल पर कुछ इस तरह दिखाई देता है:

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

मेरा कोड सही तरीके से काम कर रहा है। जब मैं दौड़ता हूं तो मैं देख सकता हूं, {column}लेकिन ऑनक्लिक इवेंट में इसे प्राप्त नहीं कर सकता।

मेरा कोड:

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

मैं onClickप्रतिक्रिया जेएस में घटना के लिए एक मूल्य कैसे पारित कर सकता हूं ?



2
इसके बजाय स्वयं का उपयोग करने पर विचार करें। यह काफी भ्रामक है क्योंकि इसे "यह" (वास्तव में महत्वपूर्ण नहीं है, हालांकि, प्रत्येक अपने स्वयं के लिए) का पर्याय होना चाहिए
दान

बाइंड मेथड और एरो पद्धति का उपयोग करके हम ऑनक्लिक ईवेंट के लिए मान पास कर सकते हैं
मेरुगु प्रशांति

जवाबों:


1285

आसान तरीका

एक तीर समारोह का उपयोग करें:

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

यह एक नया फ़ंक्शन बनाएगा handleSortजो सही परिमों के साथ कॉल करता है ।

बेहतर तरीका

इसे एक उप-घटक में निकालें। रेंडर कॉल में एरो फंक्शन का उपयोग करने में समस्या यह है कि यह हर बार एक नया फंक्शन बनाएगा, जो अनावश्यक री-रेंडरर्स को समाप्त करता है।

यदि आप एक उप-घटक बनाते हैं, तो आप हैंडलर को पास कर सकते हैं और प्रॉप्स को तर्कों के रूप में उपयोग कर सकते हैं, जो तब ही फिर से प्रस्तुत करेगा जब प्रॉप्स बदल जाएगा (क्योंकि हैंडलर संदर्भ अब कभी नहीं बदलता है):

उप-घटक

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

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

मुख्य घटक

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

पुराना आसान तरीका (ES5)

.bindइच्छित पैरामीटर को पास करने के लिए उपयोग करें :

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

7
प्रतिक्रिया देता है जब मैं अपने कोड की तरह उपयोग चेतावनी देता है। मैंने अपना कोड onClick = {that.onClick.bind (null, column)} में बदल दिया है
user1924375

12
आप इस <a>टैग का उपयोग कैसे करेंगे जहां आपको घटना को पास करने की आवश्यकता है, उपयोग करने के लिएpreventDefault()
साइमन एच

38
@SimonH आपके द्वारा पास किए गए तर्कों के बाद घटना को अंतिम तर्क के रूप में पारित किया जाएगा bind
धब्बा

47
क्या यह प्रदर्शन के लिए बुरा नहीं है? प्रत्येक रेंडर पर एक नया फ़ंक्शन नहीं बनाया जाएगा?
एंड्रयूमैक्गन

13
@AndrewMcLagan है। मुझे यह नियम और सबसे अच्छा समाधान का वर्णन करने के लिए मिला
ई। सुंदरिन

140

यहां अच्छे जवाब हैं, और मैं @Austin ग्रीको (अलग घटकों के साथ दूसरा विकल्प) से सहमत हूं,
एक और तरीका है जैसे मुझे, करी
आप जो कर सकते हैं, वह एक ऐसा कार्य है जो एक पैरामीटर (आपका पैरामीटर) को स्वीकार करता है और एक अन्य फ़ंक्शन देता है जो किसी अन्य पैरामीटर (इस मामले में क्लिक घटना) को स्वीकार करता है। फिर आप इसके साथ स्वतंत्र हैं जो आप कभी भी चाहते हैं।

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

और आप इसे इस तरह से उपयोग करेंगे:

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

इस तरह के उपयोग का एक पूरा उदाहरण यहां दिया गया है:

ध्यान दें कि यह दृष्टिकोण प्रत्येक रेंडर पर एक नए उदाहरण के निर्माण को हल नहीं करता है।
मुझे अन्य इनलाइन हैंडलर पर यह दृष्टिकोण पसंद है क्योंकि यह मेरी राय में अधिक संक्षिप्त और पठनीय है।

संपादित करें:
जैसा कि नीचे टिप्पणी में सुझाया गया है, आप फ़ंक्शन के परिणाम को कैश / मेमो कर सकते हैं।

यहाँ एक भोली कार्यान्वयन है:


12
यह स्वीकृत उत्तर होना चाहिए। वास्तव में लागू करना आसान है और आपको किसी अन्य घटक को बनाने या अलग से बांधने की आवश्यकता नहीं है। धन्यवाद!
Tamb

29
बेहतर लगता है, लेकिन एक प्रदर्शन के नजरिए से, हालांकि, करीने से वास्तव में मदद नहीं मिलती है, क्योंकि यदि आप दो बार हैंडल को कॉल करते हैं, तो एक ही परम के साथ, आपको दो फ़ंक्शन मिलते हैं जो जेएस इंजन को अलग-अलग ऑब्जेक्ट मानते हैं, भले ही वे एक ही काम करें। । तो आप अभी भी फिर से प्रस्तुत करना। प्रदर्शन के लिए, आपको प्रदर्शन लाभ प्राप्त करने के लिए हैंडलचेंज के परिणामों को कैश करना होगा। जैसेhandleChange = param => cache[param] || (e => { // the function body })
१38

6
यह सही उत्तर है यदि आप @travellingprog
llioor

2
क्या कोई लिंक प्रदान कर सकता है या बता सकता है कि यह कैशिंग तंत्र कैसे काम करता है? धन्यवाद।
सदोक मंदिर

2
सुंदर और साफ!
हेटम अलीम

117

आजकल, ES6 के साथ, मुझे लगता है कि हम एक अद्यतन जवाब का उपयोग कर सकते हैं।

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

मूल रूप से, (किसी के लिए भी जो नहीं जानते) onClickउम्मीद कर रहा है कि कोई फ़ंक्शन इसे पारित bindकरता है , काम करता है क्योंकि यह एक फ़ंक्शन की प्रतिलिपि बनाता है। इसके बजाय हम एक एरो फंक्शन एक्सप्रेशन पास कर सकते हैं, जो केवल हमारे द्वारा इच्छित फंक्शन को इनवाइट करता है, और संरक्षित करता है this। आपको कभी भी renderप्रतिक्रिया में विधि को बाँधने की आवश्यकता नहीं होनी चाहिए , लेकिन अगर किसी कारण से आप thisअपने किसी घटक तरीके से हार रहे हैं :

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

10
आपको कभी भी बांधने की ज़रूरत नहीं है render()क्योंकि इसे रिएक्ट कहा जाता है। यदि कुछ है, तो आपको bindईवेंट हैंडलर की आवश्यकता है , और केवल तब जब आप तीर का उपयोग नहीं कर रहे हैं।
दान अब्रामोव

1
@DanAbramov मुझे लगता है कि आप सही हैं, लेकिन मैंने इसे सिर्फ मामले में शामिल किया है - एक उदाहरण के साथ अद्यतन किया गया है जो कि अंतर्निहित रूप से रेंडरिंग रेंडर नहीं करता है।
अनिकेरु

3
ध्यान दें कि पास propsकरना सबसे अच्छा है super()या this.propsकंस्ट्रक्टर के दौरान अपरिभाषित रहेगा जो भ्रमित हो सकता है।
दान अब्रामोव

2
क्या हासिल करना है? आप कार्यात्मक घटक के अंदर एक हैंडलर को परिभाषित कर सकते हैं और इसे पास कर सकते हैं। यह हर एक रेंडर एक अलग कार्य होगा इसलिए यदि आपने एक प्रोफाइलर के साथ यह निर्धारित किया है कि यह आपको पूर्ण मुद्दे देता है (और केवल अगर आप इस पर निश्चित हैं!), इसके बजाय एक वर्ग का उपयोग करने पर विचार करें।
दान अब्रामोव

1
@ me-me हाँ, और यदि आप बैबल में एजिंग ब्लीडिंग एज ऑप्ट-इन करते हैं, तो आपको अपनी कक्षा पर गुणों को घोषित करना चाहिए foo = () => {...}और फिर <button onClick={this.foo}...एक तीर फ़ंक्शन को शामिल करने का एकमात्र कारण प्रस्तुत करना होगा यदि आप इस तरह से बैबल का उपयोग करते हैं, तो IMO, अगर आप कुछ वैरिएबल को कैप्चर करना चाहते हैं, जो केवल रेंडर () पद्धति के दायरे में मौजूद है (ईवेंट्स को केवल पास किया जा सकता है और लागू नहीं होता है)।
अनिकेरू

73

[[h / t @ @ E.Sundin को एक टिप्पणी में जोड़ने के लिए ]

शीर्ष उत्तर (अनाम फ़ंक्शन या बाइंडिंग) काम करेगा, लेकिन यह सबसे अधिक प्रदर्शन करने वाला नहीं है, क्योंकि यह map()फ़ंक्शन द्वारा उत्पन्न हर उदाहरण के लिए ईवेंट हैंडलर की एक प्रति बनाता है ।

यह ESLint-plugin-reaction से करने के लिए इष्टतम तरीके की व्याख्या है :

वस्तुओं की सूची

रेंडर में बाइंड का एक सामान्य उपयोग मामला है जब एक सूची प्रदान करता है, प्रति सूची आइटम के लिए एक अलग कॉलबैक है:

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

इस तरह से करने के बजाय, दोहराया अनुभाग को अपने घटक में खींचें:

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

});

यह प्रतिपादन को गति देगा, क्योंकि यह हर रेंडर पर नए कार्यों (बाइंड कॉल के माध्यम से) बनाने की आवश्यकता से बचा जाता है।


क्या प्रतिक्रिया कॉल के साथ उन कार्यों को लागू करती है / लागू होती है, फिर, हुड के नीचे, और आंतरिक रूप से बाइंड करने से बचें?
एकेरू

1
वहाँ एक स्टेटलेस घटक का उपयोग कर ऐसा करने का एक तरीका है?
कार्लोस मार्टिनेज

2
@CarlosMartinez अच्छी नज़र, मैंने उदाहरण को अपडेट किया - उन्हें पहली बार में स्टेटलेस फंक्शनल कंपोनेंट (SFC) होना चाहिए था। आम तौर पर, यदि कोई घटक कभी उपयोग नहीं करता है this.state, तो आप इसे सुरक्षित रूप से एक एसएफसी के साथ स्वैप कर सकते हैं।
ब्रैंडन

3
हम्म, मुझे नहीं लगता कि यह अधिक प्रदर्शन कैसे है? हर बार ListItem फ़ंक्शन को लागू नहीं किया जाएगा, और इस प्रकार _onClick फ़ंक्शन को हर रेंडर बनाया जाएगा।
मटियास पेटर जोहानसन

1
मैं यहां एक विशेषज्ञ से बहुत दूर हूं, लेकिन जैसा कि मैं इसे समझता हूं, 'सही' पैटर्न में, हैंडलर का केवल एक उदाहरण है और यह घटक जिसे भी कॉल करता है, उसके लिए प्रस्ताव पारित किया गया है। बाइंड उदाहरण (यानी, 'गलत' पैटर्न) में, हर तात्कालिक घटक के लिए हैंडलर का एक उदाहरण है। यह एक ही कार्य को तीस बार लिखने और उसे एक बार लिखने और आवश्यकता होने पर उसे लिखने के बराबर मेमोरी की तरह है।
ब्रैंडन

25

यह मेरा दृष्टिकोण है, यह निश्चित नहीं है कि यह कितना बुरा है, कृपया टिप्पणी करें

क्लिक करने योग्य तत्व में

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

और फिर

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

यह एक ऐसा दृष्टिकोण है जिसके बारे में मैं सोच रहा था, यह थोड़ा हैकरी लगता है लेकिन एक नया घटक बनाने से बचता है। मुझे यकीन नहीं है कि एक अलग घटक में खींचने की तुलना में getAttribute बेहतर या बदतर पूर्ण-वार है।
कामरानिकस

2
मुझे लगता है कि यह एक अच्छा समाधान है क्योंकि यह बहुत सरल है। लेकिन यह केवल स्ट्रिंग मानों के साथ काम करता है, यदि आप एक वस्तु चाहते हैं तो यह काम नहीं करता है।
स्टीफन एल

एक वस्तु के लिए आपको करना होगा encodeURIComponent(JSON.stringify(myObj)), फिर उसे पार्स करने के लिए JSON.parse(decodeURIComponent(myObj)),। फ़ंक्शंस के लिए, मुझे यकीन है कि यह अभ्यस्त या नए फंक्शन () के बिना काम नहीं करेगा, दोनों से बचा जाना चाहिए। इन कारणों से मैं प्रतिक्रिया / JS में डेटा पास करने के लिए डेटा-विशेषताओं का उपयोग नहीं करता।
सोलविटेग

मैं जोड़ना चाहता हूं कि मैं इसका उपयोग अक्सर और केवल मामूली चीजों के लिए नहीं करता हूं। लेकिन आमतौर पर मैं सिर्फ एक घटक बनाता हूं और डेटा को इसके लिए सहारा देता हूं। फिर या तो उस नए घटक के अंदर क्लिक को हैंडल करें या घटक को ऑनक्लिक फ़ंक्शन पास करें। जैसे ब्रैंडन उत्तर में समझाया गया है
सैंटियागो रामिरेज़

1
डेटासेट सीधे इस तरह से आधुनिक ब्राउज़रों पर पहुँचा जा सकता है (IE11 सहित): e.currentTarget.dataset.column
gsziszi

17

यह उदाहरण आप से थोड़ा अलग हो सकता है। लेकिन मैं आपको विश्वास दिलाता हूं कि इस समस्या के लिए यह सबसे अच्छा समाधान हो सकता है। मैंने ऐसे समाधान के लिए दिन खोजे हैं जिसमें कोई प्रदर्शन समस्या न हो। और अंत में इस एक के साथ आया।

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

अपडेट करें

आप उन वस्तुओं से निपटना चाहते हैं, जिन्हें पैरामीटर माना जाता है। आप JSON.stringify(object)इसे स्ट्रिंग में बदलने और डेटा सेट में जोड़ने के लिए उपयोग कर सकते हैं ।

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

1
जब डेटा पास किया जाता है तो यह काम नहीं करता है
18

समस्या को ठीक करने के लिए JSON.stringify का उपयोग करें। @SlimSim कि चाल करना चाहिए
हन्नाद रहमान

यदि आपको इस समस्या के लिए JSON.stringify का उपयोग करने की आवश्यकता है, तो शायद इसकी सही विधि नहीं है। कड़ेपन की प्रक्रिया में बहुत अधिक स्मृति होती है।
KFE

अधिकांश मामलों में आप केवल आईडी को ही पारस मानते हैं, और अपने सोर्स ऑब्जेक्ट से उस आईडी के आधार पर वस्तु विवरण प्राप्त करते हैं। और क्यों और कैसे यह बहुत सारी मेमोरी लेता है, मुझे पता है कि JSON स्ट्राइक धीमा है, लेकिन क्लिक Fn async है और इसका डोम पर कोई या 0 प्रभाव नहीं होगा, एक बार निर्मित
हन्नाद रहमान


4

एक और विकल्प शामिल नहीं है .bindया ईएस 6 एक बच्चे के घटक का उपयोग आवश्यक प्रॉप्स के साथ माता-पिता के हैंडलर को कॉल करने के लिए है। यहाँ एक उदाहरण है (और काम करने के लिए एक लिंक नीचे है):

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

मूल विचार मूल घटक के लिए onClickफ़ंक्शन को चाइल्ड घटक के लिए पास करना है । चाइल्ड कंपोनेंट onClickफंक्शन को कॉल करता है और propsइसे पास किया गया कोई भी (और event) एक्सेस कर सकता है , जिससे आप eventमाता-पिता के भीतर किसी भी मूल्य या अन्य प्रॉप्स का उपयोग कर सकते हैं।onClick फ़ंक्शन के उपयोग कर सकते हैं।

यहां एक कोडपैन डेमो दिखाया गया है जो इस विधि को क्रिया में प्रदर्शित करता है।


4

मुझे लगता है कि यह पार्टी के लिए बहुत देर हो चुकी है, लेकिन मुझे लगता है कि एक बहुत सरल समाधान कई उपयोग मामलों को संतुष्ट कर सकता है:

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

    ...

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

मुझे लगता है कि तुम भी एक का उपयोग कर सकते हैं data- विशेषता का ।

सरल, शब्दार्थ।


4

बस इस तरह एक समारोह बनाएँ

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

और इसे उस जगह पर बुलाएं जहां आपको ज़रूरत है

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


3

ओ.पी. के प्रश्न का उत्तर देने के लिए वैकल्पिक प्रयास करना जिसमें e.preventDefault () कॉल शामिल हैं:

रेंडर किया गया लिंक ( ES6 )

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

घटक समारोह

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

3

यदि आप उपयोग कर रहे हैं तो आप बस इसे कर सकते हैं 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

नीचे से वर्णित के रूप में मुख्य से उप घटकों के पैरामीटर के रूप में गणना को एक वस्तु से कुल गिनती लागू करना।

यहाँ 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;

और यहाँ है 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>
    )
  }
};

ऊपर लागू करने का प्रयास करें और आपको सटीक परिदृश्य मिलेगा कि किसी भी DOM विधि पर Reactjs में पैरामीटर कैसे काम करते हैं।


3

मैंने एक रैपर घटक लिखा था जिसे इस उद्देश्य के लिए पुन: उपयोग किया जा सकता है जो यहां स्वीकृत उत्तरों पर बनाता है। यदि आपको केवल एक स्ट्रिंग पास करने की आवश्यकता है, तो बस एक डेटा-विशेषता जोड़ें और इसे e.target.dataset (जैसे कुछ अन्य ने सुझाव दिया है) से पढ़ें। डिफ़ॉल्ट रूप से मेरा रैपर किसी भी प्रोप से बंधेगा जो कि एक फंक्शन है और 'ऑन' से शुरू होता है और अन्य सभी तर्कों के बाद कॉल करने वाले को अपने आप ही डेटा प्रोपर पास कर देता है। हालाँकि मैंने इसे प्रदर्शन के लिए परीक्षण नहीं किया है, यह आपको स्वयं कक्षा बनाने से बचने का अवसर देगा, और इसका उपयोग इस तरह किया जा सकता है:

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

या घटकों और कार्यों के लिए

const DataInput = withData(SomeComponent);

या यदि आप पसंद करते हैं

const DataButton = withData(<button/>)

घोषित करें कि आपके कंटेनर के बाहर (आपके आयात के पास)

यहाँ एक कंटेनर में उपयोग है:

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

यहाँ आवरण कोड '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

मैं JSX onClick घटनाओं पर इस के लिए 3 सुझाव नीचे है -

  1. वास्तव में, हमें अपने कोड में .bind () या एरो फ़ंक्शन का उपयोग करने की आवश्यकता नहीं है। आप अपने कोड में सरल उपयोग कर सकते हैं।

  2. प्रदर्शन को बेहतर बनाने के लिए आप th (या ul) से tr (या li) पर भी ऑनक्लिक इवेंट को स्थानांतरित कर सकते हैं। मूल रूप से आपके पास आपके 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>

    // और आप उपयोग कर सकते हैं item.idमें onItemClickविधि के रूप में नीचे दिखाया गया है:

    onItemClick = (event) => {
       console.log(e.target.getAttribute("item.id"));
    }
  3. मैं ListItem और सूची के लिए अलग प्रतिक्रिया घटक बनाने के लिए उपर्युक्त दृष्टिकोण से सहमत हूं। यह कोड अच्छा लगता है, लेकिन यदि आपके पास १००० ली है तो १००० इवेंट श्रोता बन जाएंगे। कृपया सुनिश्चित करें कि आपके पास अधिक ईवेंट श्रोता नहीं होना चाहिए।

    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
यह तब काम नहीं करता है जब आपको पास होने के लिए आवश्यक डेटा एक वस्तु हो। विशेषता केवल स्ट्रिंग्स के साथ काम करेगी। इसके अलावा डोम से गेट एट रीडिंग शायद एक अधिक महंगा ऑपरेशन है।
स्लिमसिम

2

मैंने ऑनक्लिक ईवेंट वैल्यू पास के लिए दो तरीकों से कोड जोड़ा है। 1 है। बाइंड पद्धति का उपयोग करना 2. तीर (=>) विधि का उपयोग करना। तरीके देखते हैं handleort1 और handleort

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

नीचे उदाहरण है जो onClick घटना पर मान गुजरता है।

मैं es6 वाक्यविन्यास का उपयोग करता था। याद रखें कि क्लास कंपोनेंट एरो फंक्शन स्वचालित रूप से बंधता नहीं है, इसलिए स्पष्ट रूप से कंस्ट्रक्टर में बाध्यकारी है।

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

मुझे लगता है कि आपको रीऐक्ट के क्लास उदाहरण के लिए विधि को बांधना होगा। रिएक्टर में सभी तरीकों को बांधने के लिए एक कंस्ट्रक्टर का उपयोग करना सुरक्षित है। आपके मामले में जब आप पैरामीटर को विधि में पास करते हैं, तो पहले पैरामीटर का उपयोग विधि के 'इस' संदर्भ को बांधने के लिए किया जाता है, इस प्रकार आप विधि के अंदर मूल्य तक नहीं पहुंच सकते।


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
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
हालांकि यह कोड प्रश्न को हल कर सकता है, स्पष्टीकरण सहित वास्तव में आपकी पोस्ट की गुणवत्ता में सुधार करने में मदद करता है। याद रखें कि आप भविष्य में पाठकों के लिए प्रश्न का उत्तर दे रहे हैं, और उन लोगों को आपके कोड सुझाव के कारणों का पता नहीं चल सकता है।
श्री

2

इस सवाल से कहीं बाहर आ रहा है, लेकिन मुझे लगता है कि .bindयह चाल चलेगा। नीचे दिए गए नमूना कोड का पता लगाएं।

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

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

1

तीर फ़ंक्शन का उपयोग करना:

आपको चरण -2 स्थापित करना होगा:

npm बाबेल-प्रीसेट-स्टेज -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

इसे संभालने के 3 तरीके हैं: -

  1. निर्माता के रूप में विधि बाँधें: -

    export class HeaderRows extends Component {
       constructor() {
           super();
           this.handleSort = this.handleSort.bind(this);
       }
    }
  2. इसे बनाते समय एरो फंक्शन का उपयोग करें: -

    handleSort = () => {
        // some text here
    }
  3. तीसरा तरीका यह है: -

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

0

आप अपने कोड का उपयोग इस तरह कर सकते हैं:

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

यहाँ e ईवेंट ऑब्जेक्ट के लिए है, यदि आप preventDefault()अपने हैंडल फ़ंक्शन में ईवेंट विधियों का उपयोग करना चाहते हैं या लक्ष्य मान या जैसे नाम प्राप्त करना चाहते हैं e.target.name


0

मुझे टैग के गुण के रूप में परम को पास करने का समाधान काफी उचित लगा।

हालाँकि इसकी सीमाएँ हैं:

  • सूची आइटम के अन्य टैग होने पर ठीक से काम नहीं करता (इस प्रकार event.target का इरादा अलग हो सकता है)
  • परम केवल एक तार हो सकता है। क्रमबद्धता और डीर्सिएलाइज़ेशन की आवश्यकता है।

इसलिए मैं इस पुस्तकालय के साथ आया: प्रतिक्रिया-घटना-परम

यह:

  • जब भी आवश्यकता होती है, माता-पिता में आवश्यक विशेषता खोजकर बच्चों की समस्या को हल करता है
  • स्वचालित रूप से क्रमबद्ध और परम का वर्णन करता है
  • सेटिंग और प्राप्त करने के तर्क को एन्क्रिप्ट करता है। परम नामों के साथ खिलवाड़ करने की कोई जरूरत नहीं है

उपयोग उदाहरण:

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

बहुत सारे प्रदर्शन विचार थे, सभी शून्य में।
इस हैंडलर के साथ मुद्दा यह है कि आपको उस तर्क को शामिल करने के लिए उन पर अंकुश लगाने की आवश्यकता है, जिसे आप प्रॉप्स में नाम नहीं दे सकते।
इसका मतलब है कि घटक को प्रत्येक क्लिक करने योग्य तत्व के लिए एक हैंडलर की आवश्यकता है। आइए सहमत हैं कि कुछ बटन के लिए यह एक मुद्दा नहीं है, है ना?
समस्या तब होती है जब आप दर्जनों स्तंभों और हजारों पंक्तियों के साथ सारणीबद्ध डेटा संभाल रहे हैं। वहाँ आप कई हैंडलर बनाने के प्रभाव को देखते हैं।

तथ्य यह है, मुझे केवल एक की आवश्यकता है।
मैंने हैंडलर को टेबल स्तर (या UL या OL ...) पर सेट किया है, और जब क्लिक होता है, तो मैं बता सकता हूं कि इवेंट ऑब्जेक्ट में पहले से उपलब्ध डेटा का उपयोग करके क्लिक की गई सेल थी:

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

मैं यह जांचने के लिए टैग्नैम फ़ील्ड का उपयोग करता हूं कि क्लिक एक वैध तत्व में हुआ है, उदाहरण के लिए THs ओटी फुटर्स में क्लिक को अनदेखा करें।
RowIndex और cellIndex क्लिक की गई सेल का सही स्थान देते हैं।
Textcontent क्लिक की गई सेल का पाठ है।

इस तरह मुझे हैंडलर को सेल के डेटा को पास करने की आवश्यकता नहीं है, यह इसे स्वयं-सेवा कर सकता है।
यदि मुझे अधिक डेटा, डेटा की आवश्यकता होती है जिसे प्रदर्शित नहीं किया जाना है, तो मैं डेटासेट विशेषता या छिपे हुए तत्वों का उपयोग कर सकता हूं।
कुछ सरल डोम नेविगेशन के साथ यह सब हाथ में है।
यह तब से HTML में उपयोग किया जाता रहा है, क्योंकि पीसी बहुत आसान थे।


0

इवेंट हैंडलर में पैरामीटर पास करने के कुछ तरीके हैं, कुछ निम्नलिखित हैं।

आप किसी ईवेंट हैंडलर के चारों ओर लपेटने और पैरामीटर पास करने के लिए एक तीर फ़ंक्शन का उपयोग कर सकते हैं:

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

उपरोक्त उदाहरण कॉल करने के बराबर है .bindया आप स्पष्ट रूप से बाइंड को कॉल कर सकते हैं।

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

इन दो दृष्टिकोणों के अलावा, आप एक फ़ंक्शन के लिए तर्क भी पास कर सकते हैं जिसे करी फ़ंक्शन के रूप में परिभाषित किया गया है।

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

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

-1

एक क्लोजर का उपयोग करें , यह एक स्वच्छ समाधान में परिणाम:

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

handleSort फ़ंक्शन एक फ़ंक्शन लौटाएगा जिसमें पहले से निर्धारित मान स्तंभ है

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

उपयोगकर्ता द्वारा th पर क्लिक करने पर अनाम फ़ंक्शन को सही मान के साथ बुलाया जाएगा।

उदाहरण: https://stackblitz.com/edit/react-pass-parameters-example


-2

सरल परिवर्तन आवश्यक है:

उपयोग <th value={column} onClick={that.handleSort} >{column}</th>

के बजाय <th value={column} onClick={that.handleSort} >{column}</th>

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.