ক্লাস পদ্ধতি হিসাবে তীর ফাংশন (পাবলিক বর্গ ক্ষেত্র) কীভাবে ব্যবহার করবেন?


181

আমি প্রতিক্রিয়া সহ ES6 ক্লাসগুলি ব্যবহার করার ক্ষেত্রে নতুন, পূর্বে আমি আমার পদ্ধতিগুলি বর্তমান অবজেক্টের সাথে আবদ্ধ করে রেখেছি (প্রথম উদাহরণে দেখান), তবে ES6 কি আমাকে স্থায়ীভাবে কোনও শ্রেণীর ফাংশনকে তীরের সাহায্যে শ্রেণীর উদাহরণে আবদ্ধ করতে দেয়? (কলব্যাক ফাংশন হিসাবে পাস করার সময় কার্যকর)

class SomeClass extends React.Component {

  // Instead of this
  constructor(){
    this.handleInputChange = this.handleInputChange.bind(this)
  }

  // Can I somehow do this? Am i just getting the syntax wrong?
  handleInputChange (val) => {
    console.log('selectionMade: ', val);
  }

যাতে আমি যদি পাস SomeClass.handleInputChangeকরতে যাই , উদাহরণস্বরূপ setTimeout, এটি শ্রেণীর উদাহরণে স্কোপ হবে, না windowঅবজেক্ট।


1
আমি টাইপস্ক্রিপ্টের
মঙ্গলবার রবার্টসন

টাইপস্ক্রিপ্টের সমাধান ES7 প্রস্তাবের সমান ( গ্রহণযোগ্য উত্তর দেখুন )। এটি টাইপস্ক্রিপ্ট দ্বারা স্থানীয়ভাবে সমর্থিত।
ফিলিপ বুলি


1
আপনার ক্লাসে তীর ফাংশনগুলি ব্যবহার করা এড়ানো উচিত কারণ এগুলি প্রোটোটাইপের অংশ হবে না এবং এভাবে প্রতিটি দৃষ্টান্ত দ্বারা ভাগ করা যায় না। এটি প্রতিটি ইভেন্টে ফাংশনের একই অনুলিপি দেওয়ার মতোই।
সৌরভ রংকা

উত্তর:


205

আপনার বাক্য গঠনটি সামান্য বন্ধ রয়েছে, কেবলমাত্র সম্পত্তির নামের পরে সমান চিহ্নটি অনুপস্থিত।

class SomeClass extends React.Component {
  handleInputChange = (val) => {
    console.log('selectionMade: ', val);
  }
}

এটি একটি পরীক্ষামূলক বৈশিষ্ট্য। এটি সঙ্কলন করতে আপনাকে বাবেলে পরীক্ষামূলক বৈশিষ্ট্যগুলি সক্ষম করতে হবে। পরীক্ষামূলকভাবে সক্ষমযুক্ত একটি ডেমো এখানে

বাবেলে পরীক্ষামূলক বৈশিষ্ট্যগুলি ব্যবহার করতে আপনি এখান থেকে প্রাসঙ্গিক প্লাগইন ইনস্টল করতে পারেন । এই নির্দিষ্ট বৈশিষ্ট্যের জন্য, আপনার transform-class-propertiesপ্লাগইনটি দরকার :

{
  "plugins": [
    "transform-class-properties"
  ]
}

তুমি ক্লাসে ক্ষেত্রসমূহ এবং স্ট্যাটিক প্রোপার্টি প্রস্তাব সম্বন্ধে আরও পড়তে পারেন এখানে



4
আমার জন্য কাজ বলে মনে হচ্ছে না (যদিও আমি একজন ES6 ক্লাসের বাইরে কাজ জানেন), Babel প্রথমে একটি অপ্রত্যাশিত টোকেন তীর ছোঁড়ার =handleInputChange =
বেন

40
আপনার কিছু ব্যাখ্যা প্রদান করা উচিত, যেমন এটি কোনও ES7 প্রস্তাবনার জন্য পরীক্ষামূলক বৈশিষ্ট্য।
ফেলিক্স ক্লিং

1
বর্তমান স্পেসিফিকেশন খসড়াটি সেপ্টেম্বরে পরিবর্তন করা হয়েছিল, সুতরাং বাবেলের প্রস্তাব অনুসারে আপনি এটি অটোবাইন্ডের জন্য ব্যবহার করা উচিত নয়।
চিকো

1
বাবেল 6.3.13 এর জন্য আপনার এই প্রবন্ধগুলি প্রেরণ করতে হবে 'es2015' এবং 'সংযোগ -1' সক্রিয় করা
এন্ড্রু

12
এটি কাজ করে, তবে পদ্ধতিটি প্রোটোটাইপের সাথে যুক্ত হওয়ার পরিবর্তে কনস্ট্রাক্টরের উদাহরণটিতে যুক্ত করা হয় এবং এটির একটি বড় পার্থক্য।
lib3d

61

না, আপনি যদি আবদ্ধ, উদাহরণ-নির্দিষ্ট পদ্ধতিগুলি তৈরি করতে চান তবে আপনাকে এটি নির্মাণকারীর মধ্যে করতে হবে। তবে, আপনি .bindপ্রোটোটাইপ পদ্ধতিতে ব্যবহার না করে তার জন্য তীর ফাংশন ব্যবহার করতে পারেন :

class SomeClass extends React.Component {
  constructor() {
    super();
    this.handleInputChange = (val) => {
      console.log('selectionMade: ', val, this);
    };
    
  }
}

এমন একটি প্রস্তাব রয়েছে যা আপনাকে constructor()একই কার্যকারিতা সহ অ্যাসাইনমেন্টটি ক্লাস স্কোপটিতে সরাসরি রাখার অনুমতি দিতে পারে তবে আমি এটি উচ্চ পরীক্ষামূলক হিসাবে এটি ব্যবহার করার পরামর্শ দেব না।

বিকল্পভাবে, আপনি সর্বদা ব্যবহার করতে পারেন .bind, যা আপনাকে প্রোটোটাইপের পদ্ধতিটি ঘোষণার অনুমতি দেয় এবং তারপরে এটি কনস্ট্রাক্টরের ক্ষেত্রে উদাহরণের সাথে আবদ্ধ করে। এই পদ্ধতির আরও নমনীয়তা রয়েছে কারণ এটি আপনার শ্রেণীর বাইরের দিক থেকে পদ্ধতিটি পরিবর্তন করতে দেয় allows

class SomeClass extends React.Component {
  constructor() {
    super();
    this.handleInputChange = this.handleInputChange.bind(this);
    
  }
  handleInputChange(val) {
    console.log('selectionMade: ', val, this);
  }
}

3

আপনি তীর ফাংশন ব্যবহার করছেন এবং এটি নির্মাণকারীকে বাঁধছেন। সুতরাং যখন আপনি তীর ফাংশনগুলি ব্যবহার করেন তখন আপনাকে বাইন্ডিং করার দরকার নেই

class SomeClass extends React.Component {
  handleInputChange = (val) => {
    console.log('selectionMade: ', val);
  }
}

অথবা আপনি যখন নীচের মত স্বাভাবিক ফাংশন ব্যবহার করেন কেবল তখনই কেবল কোনও কন্সট্রাক্টরে একটি ফাংশন বাঁধতে হয়

class SomeClass extends React.Component {
   constructor(props){
      super(props);
      this.handleInputChange = this.handleInputChange.bind(this);
   }

  handleInputChange(val){
    console.log('selectionMade: ', val);
  }
}

এছাড়াও সরাসরি কোনও রেন্ডারে কোনও ফাংশনকে বাঁধাই করার পরামর্শ দেওয়া হয় না। এটি সর্বদা কনস্ট্রাক্টরে থাকা উচিত


3

আমি জানি এই প্রশ্নের যথেষ্ট উত্তর দেওয়া হয়েছে তবে এটি করার জন্য আমার কেবলমাত্র একটি ছোট অবদান রয়েছে (যারা পরীক্ষামূলক বৈশিষ্ট্যটি ব্যবহার করতে চান না তাদের জন্য)। কনস্ট্রাক্টরের একাধিক ফাংশন বাঁধতে এবং এটিকে অগোছালো দেখাতে সমস্যা হওয়ার কারণে, আমি একটি ইউটিলিটি পদ্ধতি নিয়ে এসেছি যা একবার বাঁধা এবং কনস্ট্রাক্টরে ডেকে আনা হয়েছিল, আপনার জন্য প্রয়োজনীয় সমস্ত পদ্ধতি বাইন্ডিংগুলি স্বয়ংক্রিয়ভাবে তৈরি করে?

ধরুন কনস্ট্রাক্টরের সাথে আমার এই ক্লাস রয়েছে:

//src/components/PetEditor.jsx
import React from 'react';
class PetEditor extends React.Component {
  
   constructor(props){
        super(props);
        this.state = props.currentPet || {tags:[], photoUrls: []};
     
        this.tagInput = null;
        this.htmlNode = null;

        this.removeTag = this.removeTag.bind(this);
        this.handleChange = this.handleChange.bind(this);
        this.modifyState = this.modifyState.bind(this);
        this.handleKeyUp = this.handleKeyUp.bind(this);
        this.addTag = this.addTag.bind(this);
        this.removeTag = this.removeTag.bind(this);
        this.savePet = this.savePet.bind(this);
        this.addPhotoInput = this.addPhotoInput.bind(this);
        this.handleSelect = this.handleSelect.bind(this);
        
    }
    // ... actual method declarations omitted
}

দেখে মনে হচ্ছে অগোছালো, তাই না? এখন আমি এই ইউটিলিটি পদ্ধতিটি তৈরি করেছি

//src/utils/index.js
/**
 *  NB: to use this method, you need to bind it to the object instance calling it
 */
export function bindMethodsToSelf(objClass, otherMethodsToIgnore=[]){
    const self = this;
    Object.getOwnPropertyNames(objClass.prototype)
        .forEach(method => {
              //skip constructor, render and any overrides of lifecycle methods
              if(method.startsWith('component') 
                 || method==='constructor' 
                 || method==='render') return;
              //any other methods you don't want bound to self
              if(otherMethodsToIgnore.indexOf(method)>-1) return;
              //bind all other methods to class instance
              self[method] = self[method].bind(self);
         });
}

আমার এখন যা করতে হবে তা হ'ল সেই ইউটিলিটিটি আমদানি করা, এবং আমার কনস্ট্রাক্টরের কাছে একটি কল যুক্ত করা এবং আমাকে আর নতুন কনস্ট্রাক্টরের মধ্যে নতুন পদ্ধতি আবদ্ধ করার দরকার নেই। নতুন কনস্ট্রাক্টর এখন দেখতে সুন্দর দেখাচ্ছে:

//src/components/PetEditor.jsx
import React from 'react';
import { bindMethodsToSelf } from '../utils';
class PetEditor extends React.Component {
    constructor(props){
        super(props);
        this.state = props.currentPet || {tags:[], photoUrls: []};
        this.tagInput = null;
        this.htmlNode = null;
        bindMethodsToSelf.bind(this)(PetEditor);
    }
    // ...
}


আপনার সমাধানটি দুর্দান্ত, তবে এটি সমস্ত জীবনচক্রের পদ্ধতিগুলি কভার করে না যতক্ষণ না আপনি এটিকে দ্বিতীয় যুক্তিতে ঘোষণা করেন। উদাহরণস্বরূপ: shouldComponentUpdateএবংgetSnapshotBeforeUpdate
ওয়েবডেজ ব্রায়ান

আপনার ধারণাটি অটোবাইন্ডিংয়ের মতো, এতে পারফরম্যান্সের অবক্ষয় হ্রাসযোগ্য। আপনার চারপাশে যে ফাংশন রয়েছে তা কেবল আপনাকে আবদ্ধ করতে হবে। দেখুন medium.com/@charpeni/...
মাইকেল Freidgeim
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.