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




reactjs (18)

आसान तरीका

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

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

यह एक नया फ़ंक्शन बनाएगा जो handleSort को सही 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>
);

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

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

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


Theres 'एक बहुत ही आसान तरीका है।

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

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

let memo = {};

const someArr = ["A", "B", "C", "D"];

class App extends React.Component {
  state = {
    valueA: "",
    valueB: "some initial value",
    valueC: "",
    valueD: "blah blah"
  };

  handleChange = param => {
    const handler = e => {
      const nextValue = e.target.value;
      this.setState({ ["value" + param]: nextValue });
    }
    if (!memo[param]) {
      memo[param] = e => handler(e)
    }
    return memo[param]
  };

  render() {
    return (
      <div>
        {someArr.map(obj => {
          return (
            <div key={obj}>
              <label>
                {`input ${obj}   `}
              </label>
              <input
                type="text"
                value={this.state["value" + obj]}
                onChange={this.handleChange(obj)}
              />
              <br />
              <br />
            </div>
          );
        })}
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

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

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root" />

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

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

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


ओ.पी. के प्रश्न का उत्तर देने का वैकल्पिक प्रयास करें।

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

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

घटक समारोह

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

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

आपको चरण -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; 

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

यहाँ 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 में पैरामीटर काम करते हैं।


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

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

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

इसलिए मैं इस पुस्तकालय के साथ आया: react-event-param

यह:

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

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

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;

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

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

    ...

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

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

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


मुझे लगता है, रिएक्ट के नक्शे में .bind(this, arg1, arg2, ...) - खराब कोड है, क्योंकि यह धीमा है! एकल रेंडर विधि में 10-50 .bind(this) - बहुत धीमा कोड।
मैं इसे इस तरह से ठीक करता हूं:
रेंडर विधि
<tbody onClick={this.handleClickRow}>
<tr data-id={listItem.id}>
हैंडलर
var id = $(ev.target).closest('tr').data().id

नीचे पूर्ण कोड:

return (   
    <th value={column} onClick={this.handleSort.curry(column)}  {column}</th> 
);
 table { border-collapse: collapse; } .selected td { background-color: rgba(0, 0, 255, 0.3); } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="react-dom"></div> 


मैंने एक रैपर घटक लिखा था जिसे इस उद्देश्य के लिए पुन: उपयोग किया जा सकता है जो यहां स्वीकृत उत्तरों पर बनाता है। यदि आपको केवल एक स्ट्रिंग पास करने की आवश्यकता है, तो बस एक डेटा-विशेषता जोड़ें और इसे 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. तीर (=>) विधि का उपयोग करना। तरीके देखते हैं 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>);
    }
});

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

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

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

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

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

और फिर

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

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

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 फ़ंक्शन को कॉल करता है और इसे (और event ) को दिए गए किसी भी props को एक्सेस कर सकता है, जिससे आप पेरेंट के onClick फ़ंक्शन के भीतर किसी भी event वैल्यू या अन्य प्रॉप्स का उपयोग कर सकते हैं।

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


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

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

class MyGrid extends React.Component {
  // In real, I get this from props setted by connect in Redux
  state = {
    list: [
      {id:1, name:'Mike'},
      {id:2, name:'Bob'},
      {id:3, name:'Fred'}
    ],
    selectedItemId: 3
  }
  
  render () {
    const { list, selectedItemId }  = this.state
    const { handleClickRow } = this

    return (
      <table>
        <tbody onClick={handleClickRow}>
          {list.map(listItem =>(
            <tr key={listItem.id} data-id={listItem.id} className={selectedItemId===listItem.id ? 'selected' : ''}>
              <td>{listItem.id}</td>
              <td>{listItem.name}</td>
            </tr>
          ))}
        </tbody>
      </table>
    )
  }
  
  handleClickRow = (ev) => {
    const target = ev.target
    // You can use what you want to find TR with ID, I use jQuery
    const dataset = $(target).closest('tr').data()
    if (!dataset || !dataset.id) return
    this.setState({selectedItemId:+dataset.id})
    alert(dataset.id) // Have fun!
  }
}

ReactDOM.render(<MyGrid/>, document.getElementById("react-dom"))

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

table {
  border-collapse: collapse;
}

.selected td {
  background-color: rgba(0, 0, 255, 0.3);
}

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

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="react-dom"></div>

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

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







reactjs