ReactJS - রেন্ডার কি কোনও সময় "সেটস্টেট" বলা হয়?


502

প্রতিক্রিয়া কি সমস্ত উপাদান এবং উপ উপাদানগুলি প্রতিবার setStateবলা হয়?

যদি তাই হয় তবে কেন? আমি ভেবেছিলাম ধারণাটি ছিল যে প্রতিক্রিয়া কেবলমাত্র প্রয়োজন হিসাবে সামান্য রেন্ডার হয়েছিল - যখন রাষ্ট্র পরিবর্তন হয়।

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

this.setState({'test':'me'});

আমি আশা করতাম যে stateডেটা পরিবর্তিত হলে রেন্ডারগুলি কেবল ঘটত ।

এখানে জেএস ফিডাল এবং এম্বেড স্নিপেট হিসাবে উদাহরণের কোডটি দেওয়া হয়েছে :

var TimeInChild = React.createClass({
    render: function() {
        var t = new Date().getTime();

        return (
            <p>Time in child:{t}</p>
        );
    }
});

var Main = React.createClass({
    onTest: function() {
        this.setState({'test':'me'});
    },

    render: function() {
        var currentTime = new Date().getTime();

        return (
            <div onClick={this.onTest}>
            <p>Time in main:{currentTime}</p>
            <p>Click me to update time</p>
            <TimeInChild/>
            </div>
        );
    }
});

ReactDOM.render(<Main/>, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>

[1]: http://jsfiddle.net/fp2tncmb/2/

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

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

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

হ্যাঁ তবে এটির জন্য কেবল ভার্চুয়াল ডিওএম-এ পুনরায় রেন্ডার করা দরকার যদি তখন উপাদানটি ভিন্নভাবে রেন্ডার করা হয় তবে এটি কেবল আসল ডিওএম পরিবর্তন করে। ভার্চুয়াল ডিওএম-এর আপডেটগুলি সাধারণত নগণ্য (কমপক্ষে প্রকৃত স্ক্রিনে জিনিসগুলিকে সংশোধন করার তুলনায়) তাই কল করার সময় যতবারই এটি আপডেট করার প্রয়োজন হতে পারে তখন দেখা যায় যে কোনও পরিবর্তন খুব ব্যয়বহুল এবং নিরাপদ নয় বলে ধরে নেওয়ার চেয়ে যে এটি একই রেন্ডার হওয়া উচিত।
তাদগ ম্যাকডোনাল্ড-জেনসেন

উত্তর:


569

প্রতিক্রিয়া কি সমস্ত উপাদান এবং উপ-উপাদানগুলি প্রতিবার সেটস্টেট বলা হয়?

ডিফল্টরূপে - হ্যাঁ

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

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

অফিসিয়াল ডক্স থেকে উদ্ধৃত করুন http://facebook.github.io/react/docs/comp घटक- specs.html# updating- Shlocompompupupate

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

আপনার প্রশ্নের পরবর্তী অংশ:

যদি তাই হয় তবে কেন? আমি ভেবেছিলাম ধারণাটি ছিল যে প্রতিক্রিয়া কেবলমাত্র প্রয়োজন হিসাবে সামান্য রেন্ডার হয়েছিল - যখন রাষ্ট্রটি পরিবর্তিত হয়।

আমরা "রেন্ডার" বলতে পারি তার দুটি পদক্ষেপ রয়েছে:

  1. ভার্চুয়াল ডোম রেন্ডার করে: যখন রেন্ডার মেথড বলা হয় তখন এটি উপাদানটির একটি নতুন ভার্চুয়াল ডোম কাঠামো দেয়। যেমনটি আমি আগেই বলেছি, আপনি সেটস্টেট () কল করার সময় এই রেন্ডার পদ্ধতিটি সবসময় বলা হয় , কারণ shouldComp घटकUpdate সর্বদা ডিফল্টরূপে সত্য হয়। সুতরাং, ডিফল্ট হিসাবে, প্রতিক্রিয়া এখানে কোন অপ্টিমাইজেশন আছে।

  2. নেটিভ ডোম রেন্ডারগুলি: আপনার ব্রাউজারে আসল ডোম নোডগুলি কেবল তখনই ভার্চুয়াল ডোমে পরিবর্তিত হয়েছিল এবং প্রয়োজন হিসাবে সামান্য পরিবর্তিত হয়েছিল - এটি দুর্দান্ত প্রতিক্রিয়াটির বৈশিষ্ট্য যা আসল ডোম রূপান্তরকে অনুকূল করে এবং দ্রুত প্রতিক্রিয়া দেখায়।


47
দুর্দান্ত ব্যাখ্যা! এই ক্ষেত্রে সত্যই যে প্রতিক্রিয়াটি এখনও ততোধিকভাবে জ্বলজ্বল করে তোলে তা হ'ল ভার্চুয়াল ডোম পরিবর্তিত না হলে এটি আসল ডিওএম পরিবর্তন করে না । সুতরাং যদি আমার রেন্ডার ফাংশন একই জিনিসটিকে পরপর 2 বার ফেরত দেয় তবে আসল DOM মোটেও পরিবর্তন হয় না ... ধন্যবাদ!
ব্র্যাড পার্কগুলি

1
আমি মনে করি @ টুংড ঠিক আছে - নীচে তার উত্তর দেখুন। এটি উপাদানগুলির মধ্যে পিতা-মাতার সন্তানের সম্পর্কের বিষয়। উদাহরণস্বরূপ, যদি TimeInChild একটি সহোদর হল প্রধান তারপর তার ) রেন্ডার ( অকারণে নামক করা হবে না।
gvlax

2
যদি আপনার রাজ্যে তুলনামূলকভাবে বড় জাভাস্ক্রিপ্ট অবজেক্ট (~ 1k মোট বৈশিষ্ট্য) থাকে, যা উপাদানগুলির বৃহত গাছ হিসাবে উপস্থাপিত হয় (~ 100 মোট) ... আপনি কি রেন্ডার ফাংশনগুলি ভার্চুয়াল ডোমটি নির্মাণ করতে দেবেন, বা আপনার আগে, সেট করা উচিত? রাষ্ট্রটি, নতুন রাষ্ট্রটিকে পুরানোটির সাথে ম্যানুয়ালি তুলনা করুন এবং কেবলমাত্র setStateযদি কল করে থাকেন যে কোনও পার্থক্য রয়েছে? যদি তা হয় তবে এটি কীভাবে সেরা করবেন - জসন স্ট্রিংগুলি তুলনা করুন, অবজেক্ট হ্যাশগুলি তৈরি করুন এবং তুলনা করুন, ...?
ভিনসেন্ট সেলস

1
@ পেটার, তবে ভার্চুয়াল ডোমটির পুনর্গঠন করা সত্ত্বেও, যদি পুরানো ভার্চুয়াল ডোমটি নতুন ভার্চুয়াল ডোমের মতো হয় তবে ব্রাউজারের ডোমটি স্পর্শ হবে না, তাই না?
জস্কি

3
এছাড়াও, রিঅ্যাক্ট.পিউর কম্পোনেন্ট ( reactjs.org/docs/react-api.html#reactpurecomp घटक ) ব্যবহার করে দেখুন । উপাদানগুলির স্থিতি বা প্রপসগুলি আসলে পরিবর্তিত হলে এটি কেবল আপডেট করে (পুনরায় রেন্ডার করে)। সাবধান, তবে, তুলনা অগভীর।
বিতর্ককারী

104

না, রাষ্ট্র পরিবর্তিত হলে প্রতিক্রিয়া সব কিছু রেন্ডার করে না।

  • যখনই কোনও উপাদান নোংরা হয় (এর রাজ্য পরিবর্তিত হয়), সেই উপাদানটি এবং তার শিশুদের পুনরায় রেন্ডার করা হয়। এটি কিছুটা হলেও যথাসম্ভব কম পুনরায় রেন্ডার করা। কেবলমাত্র যখন রেন্ডার বলা হয় না তখন যখন কোনও শাখা অন্য রুটে স্থানান্তরিত হয়, যেখানে তাত্ত্বিকভাবে আমাদের কোনও কিছুই পুনরায় রেন্ডার করার প্রয়োজন হয় না। আপনার উদাহরণস্বরূপ, এটির TimeInChildএকটি শিশু উপাদান Main, সুতরাং Mainপরিবর্তনের অবস্থা হয়ে গেলে এটি পুনরায় রেন্ডার হয় ।

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


হ্যাঁ, এটি সঠিক উত্তর। একটি পরীক্ষা হিসাবে React.renderComp घटक হিসাবে শেষ লাইনটি পরিবর্তন করুন (<ডিভিটি <মেন /> <টাইমইনচিল্ড /> </div>, ডকুমেন্ট.বডি) ; এবং প্রধান উপাদানটির রেন্ডার () এর বডি থেকে <টাইমইনচিল্ড /> সরান । রেন্ডার () এর TimeInChild ডিফল্ট ডাকা হবে না কারণ এটি একটি শিশু নয় প্রধান কোনো আরও অনেক কিছু।
gvlax

ধন্যবাদ, এর মতো স্টাফগুলি কিছুটা কৃপণ, সেই কারণেই প্রতিক্রিয়া লেখকরা পরামর্শ দিয়েছেন যে render()পদ্ধতিটি "খাঁটি" হওয়া উচিত - বাহ্যিক অবস্থার চেয়ে স্বতন্ত্র।
টুংড

3
@ টুংড, এর অর্থ কী some branch is moved to another root? তুমি কি ডাকো branch? তুমি কি ডাকো root?
সবুজ

2
আমি সত্যিই উত্তরটি সঠিক হিসাবে চিহ্নিত হিসাবে পছন্দ করি। আমি আপনার 'রেন্ডারিং' এর স্থানীয় নেটিভ, 'রিয়েল', সাইডের ব্যাখ্যা বুঝতে পারি ... তবে আপনি যদি এটিকে রিটিক-নেটিভ দিক থেকে দেখেন তবে আপনাকে অবশ্যই বলতে হবে যে এটি আবার রেন্ডার করে। ভাগ্যক্রমে সত্যই কি পরিবর্তন হয়েছে তা নির্ধারণ করতে এবং কেবলমাত্র এই বিষয়গুলি আপডেট করার জন্য এটি যথেষ্ট স্মার্ট। এই উত্তরটি নতুন ব্যবহারকারীদের জন্য বিভ্রান্তিকর হতে পারে, প্রথমে আপনি না বলুন, এবং তারপরে আপনি ব্যাখ্যা করুন যে জিনিসগুলি রেন্ডার হয়ে যায় ...
WiRa

1
@ টুংড আপনি দয়া করে গ্রিনের প্রশ্নটি ব্যাখ্যা করতে পারেনwhat does it mean some branch is moved to another root? What do you call branch? What do you call root?
madhu131313

6

যদিও এটি এখানে অন্যান্য উত্তরগুলির মধ্যে বেশ কয়েকটিতে বলা আছে, উপাদানটিটি হয়:

  • shouldComponentUpdateরাষ্ট্র বা সম্পত্তি পরিবর্তন হলেই রেন্ডার করতে প্রয়োগ করুন implement

  • একটি পিউরকম্পোনেন্টকে প্রসারিত করতে স্যুইচ করুন , যা ইতিমধ্যে shouldComponentUpdateঅগভীর তুলনার জন্য অভ্যন্তরীণভাবে একটি পদ্ধতি প্রয়োগ করে ।

এখানে এমন একটি উদাহরণ রয়েছে যা ব্যবহার করে shouldComponentUpdate, যা কেবলমাত্র এই সাধারণ ব্যবহারের ক্ষেত্রে এবং প্রদর্শনের উদ্দেশ্যে কাজ করে for এটি ব্যবহার করা হলে, উপাদানটি প্রতিটি ক্লিকে নিজেকে পুনরায় রেন্ডার করে না, এবং প্রথম প্রদর্শিত হওয়ার পরে এবং এটি একবার ক্লিক করার পরে রেন্ডার হয়।

var TimeInChild = React.createClass({
    render: function() {
        var t = new Date().getTime();

        return (
            <p>Time in child:{t}</p>
        );
    }
});

var Main = React.createClass({
    onTest: function() {
        this.setState({'test':'me'});
    },

    shouldComponentUpdate: function(nextProps, nextState) {
      if (this.state == null)
        return true;
  
      if (this.state.test == nextState.test)
        return false;
        
      return true;
  },

    render: function() {
        var currentTime = new Date().getTime();

        return (
            <div onClick={this.onTest}>
            <p>Time in main:{currentTime}</p>
            <p>Click me to update time</p>
            <TimeInChild/>
            </div>
        );
    }
});

ReactDOM.render(<Main/>, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>


5

হ্যাঁ. এটি যখন প্রতিবেদনের পরিবর্তে সেট করা যায় তখন সেটাকে "রেন্ডার" পদ্ধতিটি কল করে যখন "shouldCompenderUpdate" মিথ্যা ফিরিয়ে দেয়।


7
দয়া করে আরও
কার্তিক রমেশ

2

"হারানো আপডেট" এর আর একটি কারণ পরবর্তী হতে পারে:

  • যদি স্ট্যাটিক getDerivedStateFromProps তারপর সংজ্ঞায়িত করা হয় এটা অফিসিয়াল ডকুমেন্টেশন অনুযায়ী প্রত্যেক আপডেটে প্রক্রিয়ায় পুন: প্রকাশ করা হয় https://reactjs.org/docs/react-component.html#updating
  • সুতরাং যদি সেই রাজ্যের মান শুরুতে প্রপস থেকে আসে তবে এটি প্রতিটি আপডেটে ওভাররাইট হয়।

যদি সমস্যা হয় তবে আপডেটের সময় আপনি রাজ্য সেট করা এড়াতে পারেন, আপনার এই জাতীয় প্যারামিটার মানটি পরীক্ষা করা উচিত

static getDerivedStateFromProps(props: TimeCorrectionProps, state: TimeCorrectionState): TimeCorrectionState {
   return state ? state : {disable: false, timeCorrection: props.timeCorrection};
}

আর একটি সমাধান হ'ল রাজ্যে একটি প্রাথমিক সম্পত্তি যুক্ত করা এবং এটি প্রথমবারে সেট আপ করা (যদি রাষ্ট্রটি শূন্য নয় এমন মান দিয়ে শুরু করা হয়))


0

সমস্ত উপাদান নয়।

stateকম্পোনেন্ট সৌন্দর্য পুরো অ্যাপ্লিকেশন রাজ্যের জলপ্রপাত উৎস পছন্দ করি।

সুতরাং পরিবর্তনটি সেটস্টেট যেখানে ডেকেছে সেখান থেকেই ঘটে। rendersতারপরে গাছটি সেখান থেকে ডেকে আনে। আপনি যদি খাঁটি উপাদান ব্যবহার করেন renderতবে তা বাদ দেওয়া হবে।

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