জেএসএক্স প্রপসগুলিকে তীর ফাংশন বা বাঁধাই কেন ব্যবহার করা উচিত নয়?


103

আমি আমার প্রতিক্রিয়া অ্যাপ্লিকেশনটির সাথে লিঙ্ক চালাচ্ছি এবং আমি এই ত্রুটিটি পেয়েছি:

error    JSX props should not use arrow functions        react/jsx-no-bind

এবং এখানেই আমি তীর ফাংশনটি চালাচ্ছি (ভিতরে onClick):

{this.state.photos.map(tile => (
  <span key={tile.img}>
    <Checkbox
      defaultChecked={tile.checked}
      onCheck={() => this.selectPicture(tile)}
      style={{position: 'absolute', zIndex: 99, padding: 5, backgroundColor: 'rgba(255, 255, 255, 0.72)'}}
    />
    <GridTile
      title={tile.title}
      subtitle={<span>by <b>{tile.author}</b></span>}
      actionIcon={<IconButton onClick={() => this.handleDelete(tile)}><Delete color="white"/></IconButton>}
    >
      <img onClick={() => this.handleOpen(tile.img)} src={tile.img} style={{cursor: 'pointer'}}/>
    </GridTile>
  </span>
))}

এটি কি একটি খারাপ অভ্যাস যা এড়ানো উচিত? এবং এটি করার সর্বোত্তম উপায় কী?

উত্তর:


170

আপনি জেএসএক্স প্রপসগুলিতে কেন ইনলাইন তীর ফাংশন ব্যবহার করবেন না

জেএসএক্সে তীর ফাংশন বা বাঁধাই ব্যবহার করা একটি খারাপ অনুশীলন যা কর্মক্ষমতা ক্ষতি করে, কারণ প্রতিটি রেন্ডারে ফাংশনটি পুনরায় তৈরি করা হয়।

  1. যখনই কোনও ফাংশন তৈরি করা হয়, পূর্ববর্তী ফাংশনটি আবর্জনা সংগ্রহ করা হয়। অনেক উপাদান পুনরায় সরবরাহ করা অ্যানিমেশনগুলিতে জাঙ্ক তৈরি করতে পারে।

  2. একটি ইনলাইন তীর ফাংশন PureComponentব্যবহারের shallowCompareফলে এবং উপাদানগুলি যে shouldComponentUpdateপদ্ধতিতে ব্যবহার করে যাইহোক রেন্ডার করতে পারে। যেহেতু তীর ফাংশন প্রপ প্রতিবার পুনরায় তৈরি করা হয়েছে, অগভীর তুলনা এটিকে প্রপতে পরিবর্তন হিসাবে চিহ্নিত করবে এবং উপাদানটি পুনরায় সরবরাহ করবে।

আপনি নীচের 2 টি উদাহরণে দেখতে পারেন - যখন আমরা ইনলাইন তীর ফাংশনটি ব্যবহার করি, <Button> প্রতিটি সময় উপাদানটি পুনরায় সরবরাহ করা হয় (কনসোলটি 'রেন্ডার বোতাম' পাঠ্য দেখায়) shows

উদাহরণ 1 - ইনলাইন হ্যান্ডলার ছাড়াই পিওরকমম্পোনেন্ট

উদাহরণ 2 - ইনলাইন হ্যান্ডলার সহ নির্ভেজাল অংশ

বিন্যাস পদ্ধতিতে thisতীর ফাংশনটি অন্তর্ভুক্ত না করে

  1. পদ্ধতিটি নিজেই কনস্ট্রাক্টারে আবদ্ধ করা:

    class Button extends React.Component {
      constructor(props, context) {
        super(props, context);
    
        this.cb = this.cb.bind(this);
      }
    
      cb() {
    
      }
    
      render() {
        return (
          <button onClick={ this.cb }>Click</button>
        );
      }
    }
  2. একটি তীর ফাংশন সহ প্রস্তাব-শ্রেণি-ক্ষেত্রগুলি ব্যবহার করে একটি পদ্ধতি বাঁধাই । এটি একটি পর্যায় 3 প্রস্তাবনা হিসাবে, আপনাকে স্টেজ 3 প্রিসেট যুক্ত করতে হবে বা শ্রেণীর বৈশিষ্ট্যগুলি আপনার বাবেল কনফিগারেশনে রূপান্তর করতে হবে।

    class Button extends React.Component {
      cb = () => { // the class property is initialized with an arrow function that binds this to the class
    
      }
    
      render() {
        return (
          <button onClick={ this.cb }>Click</button>
        );
      }
    }

অভ্যন্তরীণ কলব্যাক সহ ফাংশন উপাদান

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

উদাহরণ 1 - অভ্যন্তরীণ কলব্যাক সহ ফাংশন উপাদান:

এই সমস্যাটি সমাধান করার জন্য, আমরা হুক দিয়ে কলব্যাকটি useCallback()গুটিয়ে রাখতে পারি , এবং নির্ভরতাগুলি খালি অ্যারেতে সেট করতে পারি।

নোট:useState উত্পন্ন ফাংশন একটি আপডেটার ফাংশন, যা বর্তমান রাষ্ট্র উপলব্ধ গ্রহণ করে। এইভাবে, আমাদের বর্তমান রাষ্ট্রের নির্ভরতা নির্ধারণ করার দরকার নেই useCallback

উদাহরণ 2 - অভ্যন্তরীণ কলব্যাকের সাথে ফাংশন উপাদানটি ব্যবহারের কলব্যাকের সাথে আবৃত:


3
রাষ্ট্রবিহীন উপাদানগুলিতে আপনি কীভাবে এটি অর্জন করবেন?
লাক্স

4
স্টেটলেস (ফাংশন) উপাদানগুলি নেই this, তাই আবদ্ধ করার মতো কিছুই নেই। সাধারণত পদ্ধতিগুলি একটি মোড়কের স্মার্ট উপাদান দ্বারা সরবরাহ করা হয়।
ওরি দ্রোড়ি

39
@ ওরিডোরি: আপনার যখন কলব্যাকে ডেটা পাস করার দরকার পড়ে তখন কীভাবে এটি কাজ করে? onClick={() => { onTodoClick(todo.id) }
অ্যাডাম-বেক 20

4
@ অ্যাডাম-বেক - ক্লাসে কলব্যাক পদ্ধতির সংজ্ঞায় এটি যুক্ত করুন cb() { onTodoClick(this.props.todo.id); }
ওরি দ্রোড়ি

2
@ অ্যাডাম-বেক আমি মনে করি useCallbackগতিশীল মান সহ এটি কীভাবে ব্যবহার করা যায় । stackoverflow.com/questions/55006061/…
শোটা তমুরা

9

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

আপনি পুরো ব্যাখ্যাটি এবং আরও কিছু তথ্য দেখতে পারেন https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md


শুধু তাই নয় প্রতিবার নতুন ফাংশন দৃষ্টান্ত তৈরির অর্থ হল রাষ্ট্রটি সংশোধিত হয়েছে এবং যখন কোনও উপাদানগুলির রাজ্যটি পরিবর্তন করা হবে তখন তা পুনরায় রেন্ডার হবে। যেহেতু প্রতিক্রিয়া ব্যবহারের অন্যতম প্রধান কারণ হ'ল পরিবর্তিত উপাদানগুলি রেন্ডার করা, bindএখানে ব্যবহার করা বা তীর ফাংশনগুলি নিজেকে পাদদেশে শুটিং করছে। এটা তোলে হয় না ভাল, যদিও নথিভুক্ত বিশেষত সঙ্গে কাজ ক্ষেত্রে mapতালিকাসমূহ মধ্যে পিং অ্যারে, ইত্যাদি
hippietrail

"প্রতিটি বার নতুন ফাংশন দৃষ্টান্ত তৈরির অর্থ হল রাষ্ট্রটি সংশোধিত হয়েছে" এর অর্থ আপনি কী বোঝাতে চাইছেন? প্রশ্নটিতে
মোটেও

4

একই যুক্তি সহ নতুন ফাংশন তৈরি এড়াতে আপনি ফাংশন বাইন্ডের ফলাফলটি স্মরণ করতে পারেন, এটি করার জন্য এখানে একটি সাধারণ ইউটিলিটি দেওয়া হয়েছে memobind: https://github.com/supnate/memobind


4

এর মতো ইনলাইন ফাংশন ব্যবহার করা পুরোপুরি ঠিক। প্রসারণের নিয়মটি পুরানো।

এই নিয়মটি এমন সময় থেকে যখন তীর ফাংশনগুলি সাধারণ ছিল না এবং লোকেরা ব্যবহার করত ind কর্মক্ষমতা ইস্যুটি ক্রোম 49-এ স্থির করা হয়েছে।

আপনি কোনও সন্তানের উপাদানগুলির প্রপস হিসাবে ইনলাইন ফাংশনগুলি পাস করবেন না সেদিকে মনোযোগ দিন।

রিয়্যাক্ট রাউটারের লেখক রায়ান ফ্লোরেন্স এ সম্পর্কে একটি দুর্দান্ত অংশ লিখেছেন:

https://cdb.reacttraining.com/react-inline-functions-and-performance-bdff784f5578


আপনি কী দয়া করে ইনলাইন তীর ফাংশনগুলির সাথে উপাদানগুলিতে ইউনিট টেস্টটি কীভাবে লিখবেন তা দেখাতে পারেন?
krankuba

1
@ ক্রানকুবা এই প্রশ্নটি সম্পর্কে যা ছিল তা নয়। আপনি এখনও বেনামে ফাংশনগুলিতে পাস করতে পারেন যা ইনলাইন সংজ্ঞায়িত করা হয়নি তবে এখনও পরীক্ষামূলক নয়।
sbaechler

-1

আপনি রিঅ্যাক্ট-ক্যাশেড-হ্যান্ডলার লাইব্রেরি ব্যবহার করে তীর ফাংশনগুলি ব্যবহার করতে পারেন , পুনরায় রেন্ডারিং কর্মক্ষমতা সম্পর্কে উদ্বিগ্ন হওয়ার দরকার নেই:

দ্রষ্টব্য: অভ্যন্তরীণভাবে এটি নির্দিষ্ট কী দ্বারা আপনার তীর ফাংশনকে ক্যাশে করে, পুনরায় রেন্ডারিং সম্পর্কে উদ্বিগ্ন হওয়ার দরকার নেই!

render() {

  return <div>
  {
        this.props.photos.map(photo=>
          <Photo key={photo.url}
            onClick={this.handler(photo.url, (url) => { 
                 console.log(url) })}
          />)
   }
 </div>

}

অন্যান্য বৈশিষ্ট্য:

  • নামী হ্যান্ডলার
  • তীর ফাংশন দ্বারা ইভেন্টগুলি পরিচালনা করুন
  • কী, কাস্টম আর্গুমেন্ট এবং আসল ইভেন্ট অ্যাক্সেস করুন
  • উপাদান রেন্ডারিং পারফরমেন্স
  • হ্যান্ডলারদের জন্য কাস্টম প্রসঙ্গ

প্রশ্নটি ছিল কেন আমরা এটি ব্যবহার করতে পারি না। এটি অন্য কোনও হ্যাক দিয়ে কীভাবে ব্যবহার করবেন তা নয়।
ক্যাপিল

-1

জেএসএক্স প্রপসগুলিকে তীর ফাংশন বা বাঁধাই কেন ব্যবহার করা উচিত নয়?

বেশিরভাগ ক্ষেত্রে, কারণ ইনলাইন ফাংশনগুলি অনুকূলিত উপাদানগুলির স্মৃতিভঙ্গ করতে পারে:

Ditionতিহ্যগতভাবে, প্রতিক্রিয়ায় ইনলাইন ফাংশনগুলির চারপাশের পারফরম্যান্স উদ্বেগগুলি সম্পর্কিত হয়েছে যে প্রতিটি রেন্ডারে নতুন কলব্যাকগুলি কীভাবে shouldComponentUpdateশিশু উপাদানগুলিতে অনুকূলকরণকে ভঙ্গ করে । ( ডকস )

এটি অতিরিক্ত ফাংশন তৈরির ব্যয় সম্পর্কে কম:

পারফরমেন্স ইস্যুগুলি Function.prototype.bind এখানে স্থির হয়ে গেছে এবং তীর ফাংশনগুলি হয় কোনও দেশীয় জিনিস বা বাবেল দ্বারা সরল ফাংশনে স্থানান্তরিত হয়; উভয় ক্ষেত্রেই আমরা ধরে নিতে পারি যে এটি ধীর নয়। ( প্রতিক্রিয়া প্রশিক্ষণ )

আমি বিশ্বাস করি যে লোকেরা দাবি করে যে ফাংশন তৈরি করা ব্যয়বহুল, সবসময় ভুল তথ্য দেওয়া হয়েছিল (প্রতিক্রিয়া দল এটি কখনও বলেনি)। ( টুইট )

react/jsx-no-bindনিয়ম কখন কার্যকর?

আপনি নিশ্চিত করতে চান, যে স্মৃতিযুক্ত উপাদানগুলি উদ্দেশ্য হিসাবে কাজ করে:

  • React.memo (ফাংশন উপাদান জন্য)
  • PureComponentবা কাস্টম shouldComponentUpdate(শ্রেণীর উপাদানগুলির জন্য)

এই নিয়ম মানার দ্বারা, স্থিতিশীল ফাংশন অবজেক্টের রেফারেন্সগুলি পাস করা হয়। সুতরাং উপরের উপাদানগুলি পুনরায়-রেন্ডারগুলি প্রতিরোধ করে পারফরম্যান্স অনুকূল করতে পারে, যখন আগের প্রপসগুলি পরিবর্তন হয় না।

ESLint ত্রুটি কীভাবে সমাধান করবেন?

শ্রেণি: হ্যান্ডলারটি পদ্ধতি হিসাবে বা বন্ডিংয়ের জন্য শ্রেণীর সম্পত্তি হিসাবে সংজ্ঞায়িত করুন this
হুকস: ব্যবহার করুনuseCallback

মধ্যস্তর

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

rules: {
  "react/jsx-no-bind": [ "error", { ignoreDOMComponents: true } ],
}

const Comp = () => <span onClick={() => console.log("Hello!")} />; // no warning
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.