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


120

मेरे पास है

var TestApp = React.createClass({
      getComponent: function(){
          console.log(this.props);
      },
      render: function(){
        return(
             <div>
             <ul>
                <li onClick={this.getComponent}>Component 1</li>
             </ul>
             </div>
        );
      }
});
React.renderComponent(<TestApp />, document.body);

मैं क्लिक की गई सूची तत्व की पृष्ठभूमि को रंग देना चाहता हूं। मैं रिएक्ट में यह कैसे कर सकता हूं?

कुछ इस तरह

$('li').on('click', function(){
    $(this).css({'background-color': '#ccc'});
});

जवाबों:


95

क्यों नहीं:

onItemClick: function (event) {

    event.currentTarget.style.backgroundColor = '#ccc';

},

render: function() {
    return (
        <div>
            <ul>
                <li onClick={this.onItemClick}>Component 1</li>
            </ul>
        </div>
    );
}

और यदि आप इसके बारे में अधिक प्रतिक्रियाशील होना चाहते हैं, तो आप चयनित वस्तु को इसके अभिक्रिया घटक की स्थिति के रूप में सेट करना चाह सकते हैं, फिर आइटम के रंग को निर्धारित करने के लिए उस स्थिति को देखें render:

onItemClick: function (event) {

    this.setState({ selectedItem: event.currentTarget.dataset.id });
    //where 'id' =  whatever suffix you give the data-* li attribute
},

render: function() {
    return (
        <div>
            <ul>
                <li onClick={this.onItemClick} data-id="1" className={this.state.selectedItem == 1 ? "on" : "off"}>Component 1</li>
                <li onClick={this.onItemClick} data-id="2" className={this.state.selectedItem == 2 ? "on" : "off"}>Component 2</li>
                <li onClick={this.onItemClick} data-id="3" className={this.state.selectedItem == 3 ? "on" : "off"}>Component 3</li>
            </ul>
        </div>
    );
},

आप उन डाल करना चाहते हैं <li>एक पाश में है, और आप बनाने की जरूरत है li.onऔर li.offशैलियों अपने सेट background-color


प्रतिक्रिया में मैनुअल डोम हेरफेर एक विरोधी पैटर्न है जो केवल अधिक समस्याओं की ओर जाता है। event.currentTarget.style.backgroundColor = '#ccc';जब तक आप वास्तव में यह समझ नहीं पाते कि आप क्या कर रहे हैं (अधिकांश समय, तृतीय-पक्ष विजेट को एकीकृत करते समय) सामान से बचें ।
एमिल बर्जरोन

61

दो तरीके मैं सोच सकता हूं

var TestApp = React.createClass({
    getComponent: function(index) {
        $(this.getDOMNode()).find('li:nth-child(' + index + ')').css({
            'background-color': '#ccc'
        });
    },
    render: function() {
        return (
            <div>
              <ul>
                <li onClick={this.getComponent.bind(this, 1)}>Component 1</li>
                <li onClick={this.getComponent.bind(this, 2)}>Component 2</li>
                <li onClick={this.getComponent.bind(this, 3)}>Component 3</li>
              </ul>
            </div>
        );
    }
});
React.renderComponent(<TestApp /> , document.getElementById('soln1'));

यह मेरा निजी पसंदीदा है।

var ListItem = React.createClass({
    getInitialState: function() {
        return {
            isSelected: false
        };
    },
    handleClick: function() {
        this.setState({
            isSelected: true
        })
    },
    render: function() {
        var isSelected = this.state.isSelected;
        var style = {
            'background-color': ''
        };
        if (isSelected) {
            style = {
                'background-color': '#ccc'
            };
        }
        return (
            <li onClick={this.handleClick} style={style}>{this.props.content}</li>
        );
    }
});

var TestApp2 = React.createClass({
    getComponent: function(index) {
        $(this.getDOMNode()).find('li:nth-child(' + index + ')').css({
            'background-color': '#ccc'
        });
    },
    render: function() {
        return (
            <div>
             <ul>
              <ListItem content="Component 1" />
              <ListItem content="Component 2" />
              <ListItem content="Component 3" />
             </ul>
            </div>
        );
    }
});
React.renderComponent(<TestApp2 /> , document.getElementById('soln2'));

यहाँ एक डेमो है

आशा है कि ये आपकी मदद करेगा।


8
यह रेंडर फ़ंक्शन के भीतर बाइंड को लागू करने की अनुशंसा नहीं की जाती है क्योंकि यह हर बार घटक प्रदान करने पर करेगा। आप इसे कुछ फंक्शन में ले जा सकते हैं जो जीवनचक्र की शुरुआत में चलता है
jony89

1
@ jony89 सहमत हुआ अगर .bindकोई अतिरिक्त पैरामीटर नहीं लेता है। लेकिन पहले मामले में यह करता है। मुझे नहीं लगता कि एक और तरीका है
धीरज

1
तीन अलग-अलग कार्य हैं, (जो getComponent.bind (यह, 1) के परिणाम द्वारा बनाया गया है), हालांकि वह निश्चित निर्णय हो सकता है (यह 2-3 घटकों के लिए करेगा, 20 के लिए नहीं - जब तक कि यह वास्तव में प्रदर्शन का मुद्दा नहीं है और इसे गतिशील रूप से बनाना आसान है)।
jony89

38

यहां बताया गया है कि आप इवेंट के हैंडलर पर एक प्रतिक्रिया कैसे परिभाषित करते हैं , जो es6 सिंटैक्स का उपयोग करके प्रश्न शीर्षक का उत्तर दे रहा था

import React, { Component } from 'react';

export default class Test extends Component {
  handleClick(e) {
    e.preventDefault()
    console.log(e.target)
  }

  render() {
    return (
      <a href='#' onClick={e => this.handleClick(e)}>click me</a>
    )
  }
}

9
विधियों के bindभीतर न तो और न ही तीर फ़ंक्शन का उपयोग किया जाना चाहिए, renderक्योंकि वे हर बार एक नया फ़ंक्शन बनाते हैं। इसमें घटक की स्थिति को बदलने का प्रभाव होता है, और बदले हुए राज्य के घटक हमेशा पुनः प्रदान किए जाते हैं। एकल के लिए aयह कोई बड़ी बात नहीं है। क्लिक करने योग्य वस्तुओं के साथ उत्पन्न सूचियों के लिए यह बहुत जल्दी बड़ी बात हो जाती है। यही कारण है कि इसके खिलाफ विशेष रूप से चेतावनी दी गई है।
हिप्पिएट्रेल

18

ECMA2015 का उपयोग करें। एरो फ़ंक्शंस "इसे" बहुत अधिक सहज बनाते हैं।

import React from 'react';


class TestApp extends React.Component {
   getComponent(e, index) {
       $(e.target).css({
           'background-color': '#ccc'
       });
   }
   render() {
       return (
           <div>
             <ul>
               <li onClick={(e) => this.getComponent(e, 1)}>Component 1</li>
               <li onClick={(e) => this.getComponent(e, 2)}>Component 2</li>
               <li onClick={(e) => this.getComponent(e, 3)}>Component 3</li>
             </ul>
           </div>
       );
   }
});
React.renderComponent(<TestApp /> , document.getElementById('soln1'));`

2
indexयहाँ कुछ नहीं करता है?
नॉर्थहेमरिकन

@northamerican - नहीं, यह सिर्फ वहाँ कुछ पैरामीटर स्पष्टता जोड़ने के लिए है
itcropper

5
यह वास्तव में प्रदर्शन के लिए बुरा है क्योंकि यह प्रत्येक रेंडर पर एक नया फ़ंक्शन बनाता है। देखें: stackoverflow.com/questions/36677733/…
Jochie Nabuurs

1
और कृपया प्रतिक्रिया के अंदर jQuery का उपयोग न करें यदि आपके पास नहीं है!
एमिल बर्जरॉन

13

यदि आप ES6 का उपयोग कर रहे हैं, तो यहां कुछ सरल उदाहरण कोड दिए गए हैं:

import React from 'wherever_react_is';

class TestApp extends React.Component {

  getComponent(event) {
      console.log('li item clicked!');
      event.currentTarget.style.backgroundColor = '#ccc';
  }

  render() {
    return(
       <div>
         <ul>
            <li onClick={this.getComponent.bind(this)}>Component 1</li>
         </ul>
       </div>
    );
  }
}

export default TestApp;

ES6 वर्ग निकायों में, फ़ंक्शन को अब 'फ़ंक्शन' कीवर्ड की आवश्यकता नहीं होती है और उन्हें अल्पविराम से अलग करने की आवश्यकता नहीं होती है। आप चाहें तो => वाक्यविन्यास का भी उपयोग कर सकते हैं।

यहां गतिशील रूप से बनाए गए तत्वों के साथ एक उदाहरण दिया गया है:

import React from 'wherever_react_is';

class TestApp extends React.Component {

constructor(props) {
  super(props);

  this.state = {
    data: [
      {name: 'Name 1', id: 123},
      {name: 'Name 2', id: 456}
    ]
  }
}

  getComponent(event) {
      console.log('li item clicked!');
      event.currentTarget.style.backgroundColor = '#ccc';
  }

  render() {        
       <div>
         <ul>
         {this.state.data.map(d => {
           return(
              <li key={d.id} onClick={this.getComponent.bind(this)}>{d.name}</li>
           )}
         )}
         </ul>
       </div>
    );
  }
}

export default TestApp;

ध्यान दें कि प्रत्येक गतिशील रूप से बनाए गए तत्व में एक अद्वितीय संदर्भ 'कुंजी' होना चाहिए।

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

नया ऑनक्लिक समारोह:

getComponent(object) {
    console.log(object.name);
}

डेटा ऑब्जेक्ट में पासिंग:

{this.state.data.map(d => {
    return(
      <li key={d.id} onClick={this.getComponent.bind(this, d)}>{d.name}</li>
    )}
)}

मैं अपने ली आइटम को गतिशील बनाने की कोशिश कर रहा हूं और फिर यह अपरिभाषित हो जाता है और ऑनक्लिक फ़ंक्शन इसलिए एक त्रुटि फेंकता है।
उतरा

1
मुझे बस एक समान उत्तर मिला जहां आपको उपयोग करने की आवश्यकता है। (ind) (); अनाम फ़ंक्शन के अंत में यहाँ पर विंडो को संदर्भित करता है जब तक आप बाँध नहीं बनाते ...
उतरा


6

प्रतिक्रिया तत्वों के साथ घटनाओं को संभालना डोम तत्वों पर घटनाओं को संभालने के समान है। कुछ वाक्यात्मक अंतर हैं:

  • प्रतिक्रिया की घटनाओं को नाम दिया जाता है ऊंटकेस का उपयोग करके, बजाय निचले हिस्से के।
  • JSX के साथ आप एक स्ट्रिंगर के बजाय फंक्शन को हैंडलर के रूप में पास करते हैं।

जैसा कि रिएक्ट प्रलेखन में उल्लेख किया गया है , वे इवेंट हैंडलिंग के मामले में सामान्य HTML के समान हैं, लेकिन कैमलकेस का उपयोग करके रिएक्ट में इवेंट के नाम, क्योंकि वे वास्तव में HTML नहीं हैं, वे जावास्क्रिप्ट हैं, साथ ही, आप फ़ंक्शन कॉल पास करते समय फ़ंक्शन को पास करते हैं। HTML के लिए एक स्ट्रिंग प्रारूप में, वे अलग हैं, लेकिन अवधारणाएं बहुत समान हैं ...

नीचे दिए गए उदाहरण को देखें, जिस तरह से ईवेंट को पास किया जाता है, उस पर ध्यान दें:

function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The link was clicked.');
  }

  return (
    <a href="#" onClick={handleClick}>
      Click me
    </a>
  );
}

3

import React from 'react';

class MyComponent extends React.Component {

  getComponent(event) {
      event.target.style.backgroundColor = '#ccc';
      
      // or you can write
      //arguments[0].target.style.backgroundColor = '#ccc';
  }

  render() {
    return(
       <div>
         <ul>
            <li onClick={this.getComponent.bind(this)}>Component 1</li>
         </ul>
       </div>
    );
  }
}

export { MyComponent };  // use this to be possible in future imports with {} like: import {MyComponent} from './MyComponent'
export default MyComponent;


यह अनिवार्य रूप से 11 बिंदु उत्तर के समान प्रतीत होता है, और एक सुंदर या प्रश्न का पुनरुत्थान करता है-क्यों?
डेव न्यूटन

2

class FrontendSkillList extends React.Component {
  constructor() {
    super();
    this.state = { selectedSkill: {} };
  }
  render() {
    return (
      <ul>
        {this.props.skills.map((skill, i) => (
            <li
              className={
                this.state.selectedSkill.id === skill.id ? "selected" : ""
              }
              onClick={this.selectSkill.bind(this, skill)}
              style={{ cursor: "pointer" }}
              key={skill.id}
            >
            {skill.name}
            </li>
        ))}
      </ul>
    );
  }

  selectSkill(selected) {
    if (selected.id !== this.state.selectedSkill.id) {
      this.setState({ selectedSkill: selected });
    } else {
      this.setState({ selectedSkill: {} });
    }
  }
}

const data = [
  { id: "1", name: "HTML5" },
  { id: "2", name: "CSS3" },
  { id: "3", name: "ES6 & ES7" }
];
const element = (
  <div>
    <h1>Frontend Skill List</h1>
    <FrontendSkillList skills={data} />
  </div>
);
ReactDOM.render(element, document.getElementById("root"));
.selected {
  background-color: rgba(217, 83, 79, 0.8);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

@ user544079 उम्मीद है कि यह डेमो मदद कर सकता है :) मैं क्लासनाम को टॉगल करके पृष्ठभूमि का रंग बदलने की सलाह देता हूं।


2

import React from 'react';

class MyComponent extends React.Component {

  getComponent(event) {
      event.target.style.backgroundColor = '#ccc';
      
      // or you can write
      //arguments[0].target.style.backgroundColor = '#ccc';
  }

  render() {
    return(
       <div>
         <ul>
            <li onClick={this.getComponent.bind(this)}>Component 1</li>
         </ul>
       </div>
    );
  }
}

export { MyComponent };  // use this to be possible in future imports with {} like: import {MyComponent} from './MyComponent'
export default MyComponent;


क्या आप यह बताकर इस कोड को और अधिक संदर्भ प्रदान कर सकते हैं कि यह कैसे समस्या को ठीक कर सकता है?
मेडज

1

आप React.createClone विधि का उपयोग कर सकते हैं। अपना तत्व बनाएं, इसका क्लोन बनाएं। क्लोन के निर्माण के दौरान, आप प्रॉपर इंजेक्शन लगा सकते हैं। एक onClick इंजेक्षन: विधि इस तरह से सहारा

{ onClick : () => this.changeColor(originalElement, index) }

changeColor विधि राज्य को डुप्लिकेट के साथ सेट करेगी, जिससे आप प्रक्रिया में रंग सेट कर सकते हैं।

render()
  {
    return(
      <ul>

        {this.state.items.map((val, ind) => {
          let item = <li key={ind}>{val}</li>;
          let props = { 
            onClick: () => this.Click(item, ind),
            key : ind,
            ind
          }
          let clone = React.cloneElement(item, props, [val]);
          return clone;
        })}

      </ul>
    )
  }


क्लोनिंग पूरी तरह अनावश्यक है।
एमिल बर्जरोन

-17

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

ऐसा करने के लिए 'रिएक्ट-वे' घटक की अपनी स्थिति के साथ होगा:

( c = console.log.bind console)

mock_items: [
    {
        name: 'item_a'
        uid: shortid()
    }
    {
        name: 'item_b'
        uid: shortid()
    }
    {
        name: 'item_c'
        uid: shortid()
    }
]
getInitialState: ->
    lighted_item: null
render: ->
    div null,
        ul null,
            for item, idx in @mock_items
                uid = item.uid
                li
                    key: uid
                    onClick: do (idx, uid) =>
                        (e) =>
                            # justf to illustrate these are bound in closure by the do lambda,
                            c idx
                            c uid
                            @setState
                                lighted_item: uid
                    style:
                        cursor: 'pointer'
                        background: do (uid) =>
                            c @state.lighted_item
                            c 'and uid', uid
                            if @state.lighted_item is uid then 'magenta' else 'chartreuse'
                        # background: 'chartreuse'
                    item.name

यह उदाहरण काम करता है - मैंने इसका स्थानीय स्तर पर परीक्षण किया। आप मेरे जीथब पर बिल्कुल इस उदाहरण कोड की जांच कर सकते हैं । मूलतः एनवी केवल मेरे स्वयं के व्हाइटबोर्ड आर एंड डी उद्देश्यों के लिए स्थानीय था, लेकिन मैंने इसके लिए जीथब को पोस्ट किया। यह किसी बिंदु पर लिखा जा सकता है, लेकिन आप इसे देखने के लिए Sept 8, 2016 से प्रतिबद्ध देख सकते हैं।

आम तौर पर, यदि आप देखना चाहते हैं कि रिएक्ट के लिए यह CS / no-JSX पैटर्न कैसे काम करता है, तो यहां कुछ हालिया काम देखें । यह संभव है कि मेरे पास इस ऐप विचार के लिए एक पीओसी को पूरी तरह से लागू करने का समय होगा, जिसके लिए स्टैक में NodeJS, प्राइमस, रेडिस और रिएक्ट शामिल हैं।


पृष्ठभूमि को doलंबोदर नहीं होना चाहिए : यह अभिव्यक्ति भी काम करती है:background: if @state.lighted_item is uid then 'magenta' else 'chartreuse'
विली कुलिक

हैलो, मैं ब्राउज़र कंसोल पर onclick कैसे देख सकता हूं?
मुनीम हबीब

12
आप किसी प्रश्न के उत्तर में CoffeeScript का उपयोग क्यों करेंगे जो किसी भी तरह से इसका उल्लेख नहीं करता है? इसका कोई मतलब नहीं है और यह प्रश्नकर्ता के लिए पढ़ने के लिए उत्तर को कठिन बना सकता है, क्योंकि वह कॉफीस्क्रिप्ट को नहीं जानता / पसंद कर सकता है। डाउनवोटिंग, जाहिर है।
मैकबेम

7
नहीं, लेकिन यह भाषा के शीर्ष पर निर्मित कुछ है, निरपेक्षता मानक नहीं है और इसे स्थापित करने, और संकलन की आवश्यकता है। यह वास्तव में एक खराब विकल्प था जब कॉफ़ीसस्क्रिप्ट में अपना जवाब लिखने के लिए जब ज़ीरो इशारा कर रहा हो कि वे अपनी परियोजना में कॉफ़ीस्क्रिप्ट का उपयोग कर रहे हैं
TheRealMrCrowley

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