javascript - ईवेंट हैंडलर के अंदर प्रतिक्रिया उदाहरण (यह) तक पहुंचने में असमर्थ




6 Answers

this.changeContent को इस घटक के माध्यम से घटक उदाहरण के लिए बाध्य होना आवश्यक है this.changeContent.bind(this) प्रोप के रूप में पारित होने से पहले, अन्यथा this चर के फ़ंक्शन के बॉडी में घटक आवृत्ति को संदर्भित नहीं करेगा बल्कि windowFunction::bind देखें।

ES6 कक्षाओं के बजाय React.createClass का उपयोग करते React.createClass , किसी घटक पर परिभाषित प्रत्येक गैर-जीवन चक्र विधि स्वचालित रूप से घटक उदाहरण से जुड़ी होती है। Autobinding देखें।

ध्यान रखें कि एक फ़ंक्शन बाध्यकारी एक नया फ़ंक्शन बनाता है। आप या तो इसे सीधे प्रस्तुत करने में बाध्य कर सकते हैं, जिसका मतलब है कि हर बार घटक प्रस्तुत करने पर एक नया फ़ंक्शन बनाया जाएगा, या इसे आपके कन्स्ट्रक्टर में बांध देगा, जो केवल एक बार आग लग जाएगा।

constructor() {
  this.changeContent = this.changeContent.bind(this);
}

बनाम

render() {
  return <input onChange={this.changeContent.bind(this)} />;
}

रेफरी घटक उदाहरण पर सेट हैं और React.refs पर नहीं: आपको React.refs.someref को this.refs.someref बदलने की आवश्यकता है। आपको घटक घटक को sendContent विधि को बाध्य करने की भी आवश्यकता होगी ताकि यह this संदर्भ हो।

मैं ES6 (BabelJS के साथ) में एक साधारण घटक लिख रहा हूं, और यह कार्य करता है this.setState काम नहीं कर रहा है।

विशिष्ट त्रुटियों में कुछ शामिल है

अपरिभाषित संपत्ति 'setState' नहीं पढ़ सकता है

या

this.setState एक समारोह नहीं है

तुम जानते हो क्यों? यहां कोड है:

import React from 'react'

class SomeClass extends React.Component {
  constructor(props) {
    super(props)
    this.state = {inputContent: 'startValue'}
  }

  sendContent(e) {
    console.log('sending input content '+React.findDOMNode(React.refs.someref).value)
  }

  changeContent(e) {
    this.setState({inputContent: e.target.value})
  } 

  render() {
    return (
      <div>
        <h4>The input form is here:</h4>
        Title: 
        <input type="text" ref="someref" value={this.inputContent} 
          onChange={this.changeContent} /> 
        <button onClick={this.sendContent}>Submit</button>
      </div>
    )
  }
}

export default SomeClass



React.createClass() को React.createClass() करने के ES6 क्लास तरीके से React.createClass() घटक परिभाषा वाक्यविन्यास से संक्रमण करते समय यह समस्या सबसे महत्वपूर्ण चीजों में से एक है, जब हम अनुभव करते हैं।

React.createClass() बनाम this संदर्भ अंतर के कारण यह React.createClass() extends React.Component

React.createClass() का उपयोग स्वचालित रूप से this संदर्भ (मानों) को सही ढंग से बांध देगा, लेकिन ES6 कक्षाओं का उपयोग करते समय यह मामला नहीं है। इसे ES6 तरीके से करते समय ( React.Component को बढ़ाकर) this संदर्भ डिफ़ॉल्ट रूप से null है। कक्षा की गुण स्वचालित रूप से प्रतिक्रिया वर्ग (घटक) उदाहरण से बंधी नहीं होती हैं।

इस मुद्दे को हल करने के दृष्टिकोण

मैं कुल 4 सामान्य दृष्टिकोण जानता हूं।

  1. कक्षा के कन्स्ट्रक्टर में अपने कार्यों को बांधें । कई लोगों द्वारा एक सर्वोत्तम अभ्यास दृष्टिकोण के रूप में माना जाता है जो जेएसएक्स को छूने से बचाता है और प्रत्येक घटक को फिर से प्रस्तुत करने पर एक नया फ़ंक्शन नहीं बनाता है।

    class SomeClass extends React.Component {
      constructor(props) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
      }
      handleClick() {
        console.log(this); // the React Component instance
      }
      render() {
        return (
          <button onClick={this.handleClick}></button>
        );
      }
    }
    
  2. अपने कार्यों को इनलाइन बांधें । आप अभी भी कुछ ट्यूटोरियल्स / लेख / आदि में इस दृष्टिकोण का उपयोग कर सकते हैं, इसलिए यह महत्वपूर्ण है कि आप इसके बारे में जानते हों। यह # 1 की तरह एक ही अवधारणा है, लेकिन ध्यान रखें कि एक फ़ंक्शन बाध्यकारी प्रत्येक पुन: प्रस्तुत करने के लिए एक नया फ़ंक्शन बनाता है।

    class SomeClass extends React.Component {
      handleClick() {
        console.log(this); // the React Component instance
      }
      render() {
        return (
          <button onClick={this.handleClick.bind(this)}></button>
        );
      }
    }
    
  3. एक वसा तीर समारोह का प्रयोग करें । तीर कार्यों तक, हर नए समारोह ने अपना खुद का मूल्य परिभाषित किया। हालांकि, तीर फ़ंक्शन अपना स्वयं का संदर्भ नहीं बनाता है, इसलिए this संदर्भ घटक उदाहरण से मूल अर्थ है। इसलिए, हम कर सकते हैं:

    class SomeClass extends React.Component {
      handleClick() {
        console.log(this); // the React Component instance
      }
      render() {
        return (
          <button onClick={ () => this.handleClick() }></button>
        );
      }
    }
    

    या

    class SomeClass extends React.Component {
      handleClick = () => {
        console.log(this); // the React Component instance
      }
      render() {
        return (
          <button onClick={this.handleClick}></button>
        );
      }
    }
    
  4. स्वचालित रूप से अपने कार्यों को बांधने के लिए उपयोगिता फ़ंक्शन लाइब्रेरी का उपयोग करें । वहाँ कुछ उपयोगिता पुस्तकालय हैं, जो स्वचालित रूप से आपके लिए नौकरी करता है। यहां कुछ लोकप्रिय हैं, बस कुछ उल्लेख करने के लिए:

    • ऑटोबिंड डेकोरेटर एक एनपीएम पैकेज है जो इस विधि के सही उदाहरण के लिए कक्षा के तरीकों को बांधता है, भले ही विधियों को अलग किया जाए। पैकेज घटक के संदर्भ के सही संदर्भ में this बाध्य करने के तरीकों से पहले @autobind का उपयोग करता है।

      import autobind from 'autobind-decorator';
      
      class SomeClass extends React.Component {
        @autobind
        handleClick() {
          console.log(this); // the React Component instance
        }
        render() {
          return (
            <button onClick={this.handleClick}></button>
          );
        }
      }
      

      ऑटोबिंड डेकोरेटर एक स्मार्ट क्लास के अंदर सभी विधियों को एक साथ में लाने के लिए पर्याप्त स्मार्ट है, जैसे दृष्टिकोण # 1।

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

      import autobind from 'class-autobind';
      
      class SomeClass extends React.Component {
        constructor() {
          autobind(this);
          // or if you want to bind only only select functions:
          // autobind(this, 'handleClick');
        }
        handleClick() {
          console.log(this); // the React Component instance
        }
        render() {
          return (
            <button onClick={this.handleClick}></button>
          );
        }
      }
      

      पीएस: अन्य बहुत ही समान पुस्तकालय प्रतिक्रिया ऑटोबॉंड है

सिफ़ारिश करना

अगर मैं आप थे, तो मैं दृष्टिकोण # 1 के साथ रहूंगा। हालांकि, जैसे ही आपको अपने वर्ग के कन्स्ट्रक्टर में बाँधने का एक टन मिलता है, मैं आपको दृष्टिकोण # 4 में वर्णित सहायक सहायक पुस्तकालयों में से एक का पता लगाने की सलाह दूंगा।

अन्य

यह आपके पास इस मुद्दे से संबंधित नहीं है, लेकिन आपको रेफरी का उपयोग नहीं करना चाहिए

आपका पहला झुकाव आपके ऐप में "चीजें करने" के लिए रेफरी का उपयोग करना हो सकता है। यदि ऐसा है, तो एक पल लें और अधिक गंभीरता से सोचें कि राज्य पदानुक्रम में राज्य का स्वामित्व होना चाहिए।

इसी तरह के प्रयोजनों के लिए, एक नियंत्रित घटक का उपयोग करके आपको जिस तरह की आवश्यकता है, वह पसंदीदा तरीका है। मेरा सुझाव है कि आप अपने घटक state का उपयोग करने पर विचार करें। तो, आप इस तरह के मूल्य को आसानी से एक्सेस कर सकते हैं: this.state.inputContent




यह समस्या हो रही है क्योंकि यह this.changeContent और onClick={this.sendContent} घटक के उदाहरण के लिए बाध्य नहीं हैं।

ईएस 6 के तीर कार्यों का उपयोग करने के लिए कन्स्ट्रक्टर () में बाइंड () का उपयोग करने के अलावा एक और समाधान है (जो आसपास के कोड के समान व्याख्यात्मक दायरे को साझा करता है और इसे बनाए रखता है, ताकि आप अपना कोड रेंडर () में बदल सकें हो:

render() {
    return (

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

        <button onClick={ () => this.sendContent() }>Submit</button>

    )
  }



यदि आप कन्स्ट्रक्टर सिंटैक्स में बाध्य रखना चाहते हैं, तो आप proposal-bind-operator उपयोग कर सकते हैं और अपने कोड को निम्नानुसार बदल सकते हैं:

constructor() {
  this.changeContent = ::this.changeContent;
}

के बजाय :

constructor() {
  this.changeContent = this.changeContent.bind(this);
}

बहुत आसान, bind(this) या fatArrow की कोई ज़रूरत नहीं है।




यह समस्या प्रतिक्रिया 15.0 के बाद होती है, जो ईवेंट हैंडलर घटक से स्वतः बाध्य नहीं होता है। इसलिए जब भी इवेंट हैंडलर को कॉल किया जाएगा तो आपको इसे मैन्युअल रूप से घटक से बांधना होगा।

समस्या को हल करने के कई तरीके हैं। लेकिन आपको यह जानने की जरूरत है कि कौन सी विधि सर्वोत्तम है और क्यों? आम तौर पर, हम अनुशंसा करते हैं कि कक्षा के कन्स्ट्रक्टर में अपने कार्यों को बाध्यकारी करें या तीर फ़ंक्शन का उपयोग करें।

// method 1: use a arrow function
    class ComponentA extends React.Component {
      eventHandler = () => {
        console.log(this)
      }
      render() {
        return ( 
        <ChildComponent onClick={this.eventHandler} /> 
        );
      }

// method 2: Bind your functions in the class constructor.
    class ComponentA extends React.Component {
      constructor(props) {
        super(props);
        this.eventHandler = this.eventHandler.bind(this);
      }
      render() {
        return ( 
        <ChildComponent onClick={this.eventHandler} /> 
        );
      }

जब घटक हर बार प्रस्तुत करते हैं तो ये दो विधियां एक नया फ़ंक्शन नहीं बनाती हैं। इसलिए हमारे चाइल्ड कॉम्पोनेंट नए फ़ंक्शन प्रोप परिवर्तन के कारण पुनः प्रस्तुत नहीं होंगे, या प्रदर्शन समस्या उत्पन्न कर सकते हैं।




आप इसे तीन तरीकों से दूर कर सकते हैं

1. निम्नानुसार कन्स्ट्रक्टर में ईवेंट फ़ंक्शन को बाध्य करें

import React from 'react'

class SomeClass extends React.Component {
  constructor(props) {
    super(props)
    this.state = {inputContent: 'startValue'}
    this.changeContent = this.changeContent.bind(this);
  }

  sendContent(e) {
    console.log('sending input content '+React.findDOMNode(React.refs.someref).value)
  }

  changeContent(e) {
    this.setState({inputContent: e.target.value})
  } 

  render() {
    return (
      <div>
        <h4>The input form is here:</h4>
        Title: 
        <input type="text" ref="someref" value={this.inputContent} 
          onChange={this.changeContent} /> 
        <button onClick={this.sendContent}>Submit</button>
      </div>
    )
  }
}

export default SomeClass

2. जब इसे बुलाया जाता है

import React from 'react'

class SomeClass extends React.Component {
  constructor(props) {
    super(props)
    this.state = {inputContent: 'startValue'}
  }

  sendContent(e) {
    console.log('sending input content '+React.findDOMNode(React.refs.someref).value)
  }

  changeContent(e) {
    this.setState({inputContent: e.target.value})
  } 

  render() {
    return (
      <div>
        <h4>The input form is here:</h4>
        Title: 
        <input type="text" ref="someref" value={this.inputContent} 
          onChange={this.changeContent} /> 
        <button onClick={this.sendContent.bind(this)}>Submit</button>
      </div>
    )
  }
}

export default SomeClass

3. तीर कार्यों का उपयोग करके

import React from 'react'

class SomeClass extends React.Component {
  constructor(props) {
    super(props)
    this.state = {inputContent: 'startValue'}
  }

  sendContent(e) {
    console.log('sending input content '+React.findDOMNode(React.refs.someref).value)
  }

  changeContent(e) {
    this.setState({inputContent: e.target.value})
  } 

  render() {
    return (
      <div>
        <h4>The input form is here:</h4>
        Title: 
        <input type="text" ref="someref" value={this.inputContent} 
          onChange={this.changeContent} /> 
        <button onClick={()=>this.sendContent()}>Submit</button>
      </div>
    )
  }
}

export default SomeClass



Related

javascript reactjs ecmascript-6 babeljs