प्रतिक्रिया: "यह" एक घटक फ़ंक्शन के अंदर अपरिभाषित है


152
class PlayerControls extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      loopActive: false,
      shuffleActive: false,
    }
  }

  render() {
    var shuffleClassName = this.state.toggleActive ? "player-control-icon active" : "player-control-icon"

    return (
      <div className="player-controls">
        <FontAwesome
          className="player-control-icon"
          name='refresh'
          onClick={this.onToggleLoop}
          spin={this.state.loopActive}
        />
        <FontAwesome
          className={shuffleClassName}
          name='random'
          onClick={this.onToggleShuffle}
        />
      </div>
    );
  }

  onToggleLoop(event) {
    // "this is undefined??" <--- here
    this.setState({loopActive: !this.state.loopActive})
    this.props.onToggleLoop()
  }

मैं loopActiveटॉगल पर राज्य को अपडेट करना चाहता हूं , लेकिन thisहैंडलर में ऑब्जेक्ट अपरिभाषित है। ट्यूटोरियल डॉक्टर के अनुसार, मुझे thisघटक का उल्लेख करना चाहिए। क्या मैं कुछ भूल रहा हूँ?

जवाबों:


211

ES6 React.Component अपने आप में ऑटो बाइंड विधियों को नहीं करता है। आपको उन्हें खुद को कंस्ट्रक्टर में बांधने की जरूरत है। ऐशे ही:

constructor (props){
  super(props);

  this.state = {
      loopActive: false,
      shuffleActive: false,
    };

  this.onToggleLoop = this.onToggleLoop.bind(this);

}

23
यदि आप () => this.onToggleLoopअपनी प्रतिक्रिया वर्ग में onToggleLoop फ़ंक्शन को स्थानांतरित करने के बाद अपनी onClick संपत्ति को बदलते हैं तो यह भी काम करेगा।
सैम

71
क्या आपको वास्तव में हर प्रतिक्रिया वर्ग के हर तरीके को बांधना है? थोड़ा पागल नहीं है?
एलेक्स एल

6
@AlexL तरीकों को स्पष्ट रूप से बाध्य किए बिना इसे करने के तरीके हैं। यदि आप बाबेल का उपयोग करते हैं, तो प्रतिक्रिया घटक पर हर विधि को तीर के कार्यों के रूप में घोषित करना संभव है। यहाँ उदाहरण हैं: babeljs.io/blog/2015/06/07/react-on-es6-plus
इवान

7
लेकिन thisपहले स्थान पर अपरिभाषित क्यों है ? मुझे पता है thisकि जावास्क्रिप्ट इस बात पर निर्भर करता है कि फ़ंक्शन कैसे कहा जाता है, लेकिन यहां क्या हो रहा है?
मावरिक

1
लेकिन मैं यह कैसे कर सकता हूं कि निर्माण के बाद तक फ़ंक्शन को परिभाषित नहीं किया गया है? अगर मुझे कंस्ट्रक्टर में ऐसा करने की कोशिश की जाती है, तो मुझे "अपरिवर्तित संपत्ति" को पढ़ा नहीं जा सकता है, भले ही आप मेरे कार्य को कक्षा में परिभाषित करते हैं :(
रेक्स

87

कुछ तरीके हैं।

एक this.onToggleLoop = this.onToggleLoop.bind(this);कंस्ट्रक्टर में जोड़ना है।

एक और तीर कार्य है onToggleLoop = (event) => {...}

और फिर वहाँ है onClick={this.onToggleLoop.bind(this)}


1
क्यों onToogleLoop = () => {} काम करता है? मुझे वही समस्या मिली और मैंने इसे अपने कंस्ट्रक्टर में बाइंड किया लेकिन यह काम नहीं किया ... और अब मैंने आपकी पोस्ट देखी है और अपने तरीके को एरो फंक्शन सिंटैक्स से बदल दिया है और यह काम करता है। क्या आप इसे मुझे समझा सकते हैं?
गुचेलकाबेन

5
से developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... ; एक तीर फ़ंक्शन इसे स्वयं नहीं बनाता है, एन्क्लोजिंग निष्पादन संदर्भ के इस मूल्य का उपयोग किया जाता है।
जे। मार्क स्टीवंस

1
ध्यान दें कि में बाध्यकारी इनलाइन onClickवापस आ जाएगी एक नया कार्य हर प्रस्तुत करना और इस प्रकार यह की तरह एक नया मान प्रोप के लिए पारित किया गया है, के साथ खिलवाड़ लग रहा है shouldComponentUpdateमें PureComponentहै।
निन्जाकन्नन

25

अपने कार्य को इस प्रकार लिखें:

onToggleLoop = (event) => {
    this.setState({loopActive: !this.state.loopActive})
    this.props.onToggleLoop()
}

वसा तीर कार्य

कीवर्ड के लिए बाध्यकारी यह वसा तीर फ़ंक्शन के बाहर और अंदर समान है। यह फ़ंक्शन के साथ घोषित कार्यों से अलग है, जो इसे आह्वान पर किसी अन्य ऑब्जेक्ट से बांध सकता है। इस बंधन को बनाए रखना मैपिंग जैसे संचालन के लिए बहुत सुविधाजनक है: this.items.map (x => this.doSomethingWith (x))।


अगर मैं वह करूं जो मुझे मिलता है ReferenceError: fields are not currently supported
पावेल कोमारोव

यह काम करता है अगर कंस्ट्रक्टर के अंदर मैं यह कहता हूं। Func = () => {...}, लेकिन मेरा मानना ​​है कि नासमझी की तरह और संभव हो तो इससे बचना चाहते हैं।
पावेल कोमारोव

इतना भयानक है कि आप प्रतिक्रिया में सामान्य वर्ग के वाक्यविन्यास का उपयोग नहीं कर सकते हैं!
कोकडोको

11

मैं एक रेंडर फ़ंक्शन में एक समान बाइंड में भाग गया और thisनिम्नलिखित तरीके से संदर्भ को समाप्त करने में समाप्त हो गया :

{someList.map(function(listItem) {
  // your code
}, this)}

मैंने भी उपयोग किया है:

{someList.map((listItem, index) =>
    <div onClick={this.someFunction.bind(this, listItem)} />
)}

कि आप वहाँ पैदा कर रहे हैं अनावश्यक कार्यों का एक बहुत कुछ है, हर बार सूची प्रदान की जाती है ...
TJ Crowder

@TJCrowder हाँ यह सच है कि इन कार्यों को नए सिरे से प्रस्तुत किए जाने के बाद बनाया जाता है। कक्षा के तरीकों के रूप में फ़ंक्शंस बनाना और कक्षा में एक बार उन्हें बाँधना बेहतर है, लेकिन शुरुआती के लिए मैनुअल संदर्भ बंधन सहायक हो सकता है
duhaime

2

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

thisJSX संदर्भ में आपके घटक ऑब्जेक्ट के रूप में उपलब्ध है, इसलिए आप अपनी इच्छित विधि इनलाइन को thisविधि कह सकते हैं ।

यदि आप केवल फ़ंक्शन / विधि का संदर्भ देते हैं, तो ऐसा लगता है कि प्रतिक्रिया इसे स्वतंत्र फ़ंक्शन के रूप में लागू करेगी।

onClick={this.onToggleLoop} // Here you just passing reference, React will invoke it as independent function and this will be undefined

onClick={()=>this.onToggleLoop()} // Here you invoking your desired function as method of this, and this in that function will be set to object from that function is called ie: your component object

1
ठीक है, आप पहली पंक्ति का उपयोग भी कर सकते हैं, onClick={this.onToggleLoop}बशर्ते कि आपने अपने घटक वर्ग में एक क्षेत्र (संपत्ति) को परिभाषित किया होonToggleLoop = () => /*body using 'this'*/
gvlax

1

यदि आप बेबल का उपयोग कर रहे हैं, तो आप ES7 बाइंड ऑपरेटर https://babeljs.io/docs/en/babel-plugin-transform-function-bind#auto-self-binding का उपयोग करके इस 'बाइंड' करते हैं।

export default class SignupPage extends React.Component {
  constructor(props) {
    super(props);
  }

  handleSubmit(e) {
    e.preventDefault(); 

    const data = { 
      email: this.refs.email.value,
    } 
  }

  render() {

    const {errors} = this.props;

    return (
      <div className="view-container registrations new">
        <main>
          <form id="sign_up_form" onSubmit={::this.handleSubmit}>
            <div className="field">
              <input ref="email" id="user_email" type="email" placeholder="Email"  />
            </div>
            <div className="field">
              <input ref="password" id="user_password" type="new-password" placeholder="Password"  />
            </div>
            <button type="submit">Sign up</button>
          </form>
        </main>
      </div>
    )
  }

}

0

यदि आप अपने बनाए गए तरीके को जीवन चक्र विधियों में जैसे घटकडिमाउंट ... कहते हैं, तो आप केवल this.onToggleLoop = this.onToogleLoop.bind(this)और वसा तीर फ़ंक्शन का उपयोग कर सकते हैं onToggleLoop = (event) => {...}

कंस्ट्रक्टर में एक फ़ंक्शन की घोषणा का सामान्य दृष्टिकोण काम नहीं करेगा क्योंकि जीवनचक्र विधियों को पहले कहा जाता है।


0

मेरे मामले में यह समाधान था = () => {}

methodName = (params) => {
//your code here with this.something
}

0

मेरे मामले में, एक निष्क्रिय घटक के लिए, जिसे फॉरवर्ड रीफ के साथ रेफरी प्राप्त हुआ था, मुझे वही करना था जो यहाँ कहा गया है https://itnext.io/reuse-the-ref-from-forwardref-with-react-hooket-4ce9df693dd

इससे (onClick के पास 'इस' के बराबर पहुँच नहीं है)

const Com = forwardRef((props, ref) => {
  return <input ref={ref} onClick={() => {console.log(ref.current} } />
})

इसके लिए (यह काम करता है)

const useCombinedRefs = (...refs) => {
  const targetRef = React.useRef()

  useEffect(() => {
    refs.forEach(ref => {
      if (!ref) return

      if (typeof ref === 'function') ref(targetRef.current)
      else ref.current = targetRef.current
    })
  }, [refs])

  return targetRef
}

const Com = forwardRef((props, ref) => {
  const innerRef = useRef()
  const combinedRef = useCombinedRefs(ref, innerRef)

  return <input ref={combinedRef } onClick={() => {console.log(combinedRef .current} } />
})
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.