প্রতিক্রিয়া: একটি উপাদান ফাংশনের ভিতরে "এটি" অপরিজ্ঞাত


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 প্রতিক্রিয়া onent উপাদানগুলি স্বয়ংক্রিয়ভাবে পদ্ধতিগুলিকে আবদ্ধ করে না। এগুলি আপনাকে কন্সট্রাক্টরে আবদ্ধ করতে হবে। এটার মত:

constructor (props){
  super(props);

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

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

}

23
() => this.onToggleLoopঅনটগললুপ ফাংশনটিকে আপনার প্রতিক্রিয়া শ্রেণিতে স্থানান্তরিত করার পরে যদি আপনি আপনার অনক্লিক সম্পত্তি পরিবর্তন করে থাকেন তবে এটি কাজ করবে।
স্যাম

71
আপনার কি প্রতিটি প্রতিক্রিয়া শ্রেণীর প্রতিটি পদ্ধতিকে সত্যই বাঁধতে হবে? একটু পাগল কি তাই না?
অ্যালেক্স এল

6
@ অ্যালেক্সএল পদ্ধতিগুলি পরিষ্কারভাবে আবদ্ধ না করে এটি করার উপায় রয়েছে। আপনি যদি ব্যাবেল ব্যবহার করেন তবে প্রতিক্রিয়া উপাদানটিতে প্রতিটি পদ্ধতিটি তীর ফাংশন হিসাবে ঘোষণা করা সম্ভব। এখানে উদাহরণ রয়েছে: babeljs.io/blog/2015/06/07/react-on-es6-plus
ইভান

7
তবে কেন thisপ্রথম স্থানে অপরিবর্তিত? আমি জানি thisজাভাস্ক্রিপ্টে ফাংশনটি কীভাবে বলা হয় তার উপর নির্ভর করে তবে এখানে কী চলছে?
ম্যাভেরিক

1
কিন্তু আমি কীভাবে এটি করতে পারি এটি কনস্ট্রাক্টরের পরে পর্যন্ত ফাংশনটি সংজ্ঞায়িত করা হয়নি? আমি যদি কনস্ট্রাক্টরে এটি করার চেষ্টা করি তবে আমার ফাংশনটি ক্লাসে সংজ্ঞায়িত হয়: "
রেেক্স

86

বেশ কয়েকটি উপায় আছে।

একটি this.onToggleLoop = this.onToggleLoop.bind(this);কনস্ট্রাক্টর যুক্ত করা হয়।

আরেকটি হ'ল তীর ফাংশন onToggleLoop = (event) => {...}

এবং তারপর আছে onClick={this.onToggleLoop.bind(this)}


1
কেনে Google+ এ লুপ = () => {? কাজ করে? আমি একই সমস্যা পেয়েছি এবং আমি এটি আমার নির্মাতাকে বাঁধাই করেছি তবে এটি কার্যকর হয়নি ... এবং এখন আমি আপনার পোস্ট দেখেছি এবং আমার পদ্ধতিটি একটি তীর ফাংশন সিনট্যাক্সের সাথে প্রতিস্থাপন করেছি এবং এটি কাজ করে। আপনি এটা আমার ব্যাখ্যা করতে পারবেন ?
গুচেলকাবেন

5
থেকে developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... ; একটি তীর ফাংশন এটি নিজস্ব তৈরি করে না, ঘেরযুক্ত কার্যকরকরণ প্রসঙ্গে এই মানটি ব্যবহৃত হয়।
জে। মার্ক স্টিভেনস

1
নোট যে বাঁধাই ইনলাইন onClickফিরে আসবে একটি নতুন ফাংশন যে রেন্ডার এবং এইভাবে এটি মত একটি নতুন মান ঠেকনা জন্য গৃহীত হয়েছে, সঙ্গে তালগোল পাকানো দেখায় shouldComponentUpdateমধ্যে PureComponentগুলি।
নিনজাকাননন

24

আপনার ফাংশনটি এভাবে লিখুন:

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

ফ্যাট অ্যার ফাংশন

মূলশব্দটির জন্য বাইন্ডিংটি হ'ল ফ্যাট অ্যারো ফাংশনটির বাইরে এবং অভ্যন্তরে। এটি ফাংশন সহ ঘোষিত ফাংশনগুলির চেয়ে পৃথক, যা অনুরোধের সময় এটি অন্য কোনও বস্তুকে আবদ্ধ করতে পারে। এই বাইন্ডিংটি বজায় রাখা ম্যাপিংয়ের মতো ক্রিয়াকলাপগুলির জন্য খুব সুবিধাজনক: this.items.map (x => this.doSomethingWith (x))।


আমি যদি তা করি তবে আমি পাই ReferenceError: fields are not currently supported
পাভেল কোমারোভ

এটি যদি কনস্ট্রাক্টরের অভ্যন্তরে আমি বলি তবে এটি কাজ করে।
পাভেল কোমারোভ

এত ভয়াবহ যে আপনি প্রতিক্রিয়াতে সাধারণ শ্রেণির বাক্য গঠন ব্যবহার করতে পারবেন না!
কোকোডোকো

11

আমি একটি রেন্ডার ফাংশনে একই ধরণের দৌড়ে এসেছি thisএবং নিম্নলিখিত প্রসঙ্গে প্রসঙ্গটি শেষ করে শেষ করেছি :

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

আমি এটি ব্যবহার করেছি:

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

এটি সেখানে আপনি তৈরি করছেন এমন অনেক অপ্রয়োজনীয় ফাংশন, প্রতি
বারে

@ টিজে ক্রাউডার হ্যাঁ এটি সত্য যে প্রতিবার রেন্ডার করার সময় এই ফাংশনগুলি নতুন তৈরি করা হয়। ক্লাসের পদ্ধতি হিসাবে ফাংশনগুলি তৈরি করে ক্লাসে একবারে বাঁধাই ভাল, তবে নতুনদের জন্য ম্যানুয়াল প্রসঙ্গ বাঁধাই সহায়ক হতে পারে
duhaime

2

আপনার লক্ষ্য করা উচিত যে thisকীভাবে ফাংশনটি আহ্বান করা হয় তার উপর নির্ভর করে যেমন: যখন কোনও ফাংশনটিকে কোনও বস্তুর একটি পদ্ধতি হিসাবে ডাকা হয়, thisতখন এটিটিকে বস্তুটিতে সেট করা হয় যে পদ্ধতিটি কল হয়।

thisআপনার উপাদান উপাদান হিসাবে জেএসএক্স প্রসঙ্গে অ্যাক্সেসযোগ্য, যাতে আপনি আপনার পছন্দসই পদ্ধতিটিকে পদ্ধতি হিসাবে ইনলাইন কল করতে পারেন 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

আমার ক্ষেত্রে, স্টেট-লেস যে উপাদানটি forwardRef সঙ্গে সুত্র পেয়েছি, আমি কি তা এখানে বলা হয় কি ছিল https://itnext.io/reusing-the-ref-from-forwardref-with-react-hooks-4ce9df693dd

এটি থেকে (অনক্লিকের 'এর' সমতুল্যে অ্যাক্সেস নেই)

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} } />
})
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.