ReactJS রাজ্য বনাম প্রপ


121

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

অ্যাঙ্গুলারজেএস থেকে আগত, আমি আমার মডেলটিকে একটি সম্পত্তি হিসাবে উপাদানটিতে পাস করতে চাই এবং উপাদানটি সরাসরি মডেলটি পরিবর্তন করতে চাই। বা stateউজানে প্রেরণ করার সময় আমি কি মডেলটিকে বিভিন্ন বৈশিষ্ট্যে বিভক্ত করে একত্রে আবার সংকলন করব? রিঅ্যাক্টজেএস উপায় কী?

একটি ব্লগ পোস্ট সম্পাদক উদাহরণ নিন। মডেলটি সংশোধন করার চেষ্টাটি সরাসরি দেখতে দেখতে শেষ হয়:

var PostEditor = React.createClass({
  updateText: function(e) {
    var text = e.target.value;
    this.props.post.text = text;
    this.forceUpdate();
  },
  render: function() {
    return (
      <input value={this.props.post.text} onChange={this.updateText}/>
      <button onClick={this.props.post.save}/>Save</button>
    );
  }
});

যা ভুল বলে মনে হচ্ছে।

আমাদের textমডেল সম্পত্তি তৈরি করার মতো প্রতিক্রিয়ার উপায় কি এবং পছন্দগুলি stateসংরক্ষণের আগে মডেলটিতে এটি আবার সংকলন করুন:

var PostEditor = React.createClass({
  getInitialState: function() {
    return {
      text: ""
    };
  },
  componentWillMount: function() {
    this.setState({
      text: this.props.post.text
    });
  },
  updateText: function(e) {
    this.setState({
      text: e.target.value
    });
  },
  savePost: function() {
    this.props.post.text = this.state.text;
    this.props.post.save();
  },
  render: function() {
    return (
      <input value={this.state.text} onChange={this.updateText}/>
      <button onClick={this.savePost}/>Save</button>
    );
  }
});

এর জন্য কল করার প্রয়োজন নেই this.forceUpdate(), তবে মডেলটি বাড়ার সাথে সাথে (কোনও পোস্টে কোনও লেখক, বিষয়, ট্যাগ, মন্তব্য, রেটিং ইত্যাদি থাকতে পারে ...) উপাদানটি জটিল হয়ে উঠতে শুরু করে।

রিঅ্যাক্টলিংক সহ প্রথম পদ্ধতিটি কীভাবে চলবে?

উত্তর:


64

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

আপনি বাচ্চাদের কলব্যাকগুলি নীচে পাঠাতে পারেন যা আপনার ডেটা সংশোধন করতে হবে এবং তাদের সন্তানের উপাদান থেকে কল করতে পারে।

এটি.পড়গুলি বা এটি.স্টেটটি সরাসরি পরিবর্তন করা ভাল ধারণা নয়, কারণ প্রতিক্রিয়াগুলি পরিবর্তনগুলি গ্রহণ করতে সক্ষম হবে না। কারণ কারণ প্রতিক্রিয়াটি আপনার পোস্টের প্রপসের সাথে এটি পরিবর্তন হয়েছে কিনা তা নির্ধারণের জন্য অগভীর তুলনা করে।

আমি কীভাবে বাইরের থেকে কোনও অভ্যন্তরীণ উপাদানগুলিতে ডেটা প্রবাহিত হতে পারে তা দেখানোর জন্য এই jsfiddle তৈরি করেছি ।

handleClickপদ্ধতি শো (আইএম) সঠিকভাবে আপডেট অবস্থায় 3 টি উপায়:

var Outer = React.createClass({

  getInitialState: function() {
    return {data: {value: 'at first, it works'}};
  },

  handleClick: function () {

    // 1. This doesn't work, render is not triggered.
    // Never set state directly because the updated values
    // can still be read, which can lead to unexpected behavior.

    this.state.data.value = 'but React will never know!';

    // 2. This works, because we use setState

    var newData = {value: 'it works 2'};
    this.setState({data: newData});

    // 3. Alternatively you can use React's immutability helpers
    // to update more complex models.
    // Read more: http://facebook.github.io/react/docs/update.html

    var newState = React.addons.update(this.state, {
      data: {value: {$set: 'it works'}}
    });
    this.setState(newState);
 },

  render: function() {
      return <Inner data={this.state.data} handleClick={this.handleClick} />;
  }
});

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

1
হ্যাঁ, আপনি কল করতে পারেন forceUpdate, কিন্তু এই মুহুর্তে আপনি প্রতিক্রিয়া থেকে "ফাঁস" করছেন। setState()পুনরায় রেন্ডারগুলিকে ম্যানুয়ালি ট্রিগার করা এড়াতে অস্বচ্ছ মডেলটিতে একটি কলব্যাক পাস করা ভাল ।
jxg

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

97

২০১ 2016 আপডেট হচ্ছে: প্রতিক্রিয়া পরিবর্তন করা হয়েছে, এবং "প্রপস বনাম রাজ্য" ব্যাখ্যাটি খুব সহজ হয়ে গেছে। যদি কোনও উপাদানটির ডেটা পরিবর্তন করা দরকার - এটিকে একটি রাজ্যে রাখুন, অন্যথায় প্রপসগুলিতে। কারণ প্রপসগুলি কেবলমাত্র পঠনযোগ্য

প্রপস এবং রাজ্যের মধ্যে সঠিক পার্থক্য কী?

আপনি এখানে ভাল ব্যাখ্যা খুঁজে পেতে পারেন (সম্পূর্ণ সংস্করণ)

প্রপস এবং রাষ্ট্র পরিবর্তন করা


1
প্রকৃতপক্ষে সেটপ্রপস () কোনও উপাদানগুলির মধ্যে প্রপস পরিবর্তন করতে পারে এবং পুনরায় রেন্ডার করতে পারে
ওয়াইকিট কুং

2
setPropsঅবচয় করা হয়েছে এবং ব্যবহার করা উচিত নয়। প্রতিস্থাপনটি হ'ল উপাদানটি পুনরায় রেন্ডার করা এবং প্রতিক্রিয়াগুলি হ্যান্ডেল করতে দেওয়া।
jdmichal

এবং যদি আপনি কোনও ব্যাখ্যাকারী ভিডিও খুঁজছেন: youtube.com/watch?v=qh3dYM6
কেউউ

35

প্রতিক্রিয়া ডক থেকে

প্রপসগুলি অপরিবর্তনীয়: এগুলি পিতামাতার কাছ থেকে পাস হয় এবং পিতামাতার দ্বারা "মালিকানাধীন" থাকে " মিথস্ক্রিয়া বাস্তবায়নের জন্য, আমরা উপাদানটির সাথে পরিবর্তনীয় অবস্থা প্রবর্তন করি। this.state উপাদানটির ব্যক্তিগত এবং এটি.সেটস্টেট () কল করে পরিবর্তন করা যেতে পারে। যখন রাষ্ট্র আপডেট হয়, তখন উপাদানটি নিজেকে পুনরায় রেন্ডার করে।

ট্রাইস্পেস থেকে : যখন প্রপসগুলি (বা রাজ্য) আপডেট হয় (সেটপ্রোপস / সেটস্টেট বা পিতামাতার মাধ্যমে) উপাদানটিও পুনরায় রেন্ডার করে।


16

চিন্তাভাবনা থেকে প্রতিক্রিয়া থেকে একটি পড়া :

আসুন প্রত্যেকটির মধ্য দিয়ে যাই এবং কোনটি রাষ্ট্র তা নির্ধারণ করি। প্রতিটি তথ্যের টুকরো সম্পর্কে কেবল তিনটি প্রশ্ন জিজ্ঞাসা করুন:

  1. এটা কি প্রপসের মাধ্যমে কোনও পিতামাতার কাছ থেকে পাস করা হয়েছে? যদি তা হয় তবে তা সম্ভবত রাষ্ট্র নয়।
  2. সময়ের সাথে সাথে কি এর পরিবর্তন হয়? যদি তা না হয় তবে এটি সম্ভবত রাষ্ট্র নয়।

  3. আপনি কি অন্য কোনও রাজ্য বা আপনার উপাদানগুলির প্রপসের ভিত্তিতে এটি গণনা করতে পারেন? যদি তা হয় তবে তা রাষ্ট্র নয়।


13

আমি আপনার প্রশ্নের উত্তর দিচ্ছি কিনা তা আমি নিশ্চিত নই, তবে আমি খুঁজে পেয়েছি যে, বিশেষত একটি বৃহত / ক্রমবর্ধমান অ্যাপ্লিকেশনটিতে, ধারক / উপাদান উপাদানটি অবিশ্বাস্যভাবে ভালভাবে কাজ করে।

মূলত আপনার দুটি প্রতিক্রিয়া উপাদান রয়েছে:

  • একটি "খাঁটি" ডিসপ্লে উপাদান যা স্টাইলিং এবং ডোম ইন্টারঅ্যাকশন নিয়ে কাজ করে;
  • একটি ধারক উপাদান, যা বাহ্যিক ডেটা অ্যাক্সেস / সংরক্ষণ, রাজ্য পরিচালনা এবং ডিসপ্লে উপাদানকে রেন্ডারিংয়ের সাথে সম্পর্কিত।

উদাহরণ

এনবি এই উদাহরণটি সম্ভবত এই প্যাটার্নটির সুবিধাগুলির চিত্রিত করার পক্ষে খুব সাধারণ, কারণ এই জাতীয় সরল ক্ষেত্রে এটি বেশ কার্যকর।

/**
 * Container Component
 *
 *  - Manages component state
 *  - Does plumbing of data fetching/saving
 */

var PostEditorContainer = React.createClass({
  getInitialState: function() {
    return {
      text: ""
    };
  },

  componentWillMount: function() {
    this.setState({
      text: getPostText()
    });
  },

  updateText: function(text) {
    this.setState({
      text: text
    });
  },

  savePost: function() {
    savePostText(this.state.text);
  },

  render: function() {
    return (
      <PostEditor
        text={this.state.text}
        onChange={this.updateText.bind(this)}
        onSave={this.savePost.bind(this)}
      />
    );
  }
});


/**
 * Pure Display Component
 *
 *  - Calculates styling based on passed properties
 *  - Often just a render method
 *  - Uses methods passed in from container to announce changes
 */

var PostEditor = React.createClass({
  render: function() {
    return (
      <div>
        <input type="text" value={this.props.text} onChange={this.props.onChange} />
        <button type="button" onClick={this.props.onSave} />
      </div>
    );
  }
});

উপকারিতা

ডিসপ্লে লজিক এবং ডেটা / স্টেট ম্যানেজমেন্টকে আলাদা রেখে, আপনার একটি পুনরায় ব্যবহারযোগ্য ডিসপ্লে উপাদান রয়েছে যা:

  • বিক্রিয়া -উপাদান-খেলার মাঠের মতো কিছু ব্যবহার করে প্রপসের বিভিন্ন সেট দিয়ে সহজেই পুনরাবৃত্তি করা যায়
  • বিভিন্ন আচরণের জন্য আলাদা ধারক দিয়ে আবৃত করা যেতে পারে (বা আপনার অ্যাপ্লিকেশনটির বৃহত অংশগুলি তৈরি করতে অন্যান্য উপাদানগুলির সাথে একত্রিত)

আপনার কাছে একটি ধারক উপাদান রয়েছে যা সমস্ত বাহ্যিক যোগাযোগের সাথে সম্পর্কিত। আপনি যদি পরে * * তে কোনও গুরুতর পরিবর্তন করেন তবে আপনার ডেটা অ্যাক্সেসের উপায় সম্পর্কে নমনীয় হওয়া সহজ হওয়া উচিত।

এই নিদর্শনটি লিখিতকরণ এবং বাস্তবায়ন ইউনিট পরীক্ষাগুলিকে আরও অনেক সোজা করে তোলে।

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

* ফ্লাক্সের প্যাটার্নটি পড়ুন এবং মার্টি.জেএসগুলিতে একবার দেখুন , যা এই উত্তরটিকে মূলত অনুপ্রাণিত করেছে (এবং আমি ইদানীং অনেকটা ব্যবহার করছি) রেডাক্স (এবং প্রতিক্রিয়া-হ্রাস ), যা এই প্যাটার্নটি অত্যন্ত ভালভাবে প্রয়োগ করে।

2018 বা তার পরেরগুলিতে যারা এটি পড়ছেন তাদের জন্য দ্রষ্টব্য:

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


0

আমি মনে করি আপনি একটি অ্যান্টি-প্যাটার্ন ব্যবহার করছেন যা ফেসবুক ইতিমধ্যে এই লিঙ্কটিতে ব্যাখ্যা করেছে

আপনি যে জিনিসটি সন্ধান করছেন তা এখানে:

React.createClass({
  getInitialState: function() {
    return { value: { foo: 'bar' } };
  },

  onClick: function() {
    var value = this.state.value;
    value.foo += 'bar'; // ANTI-PATTERN!
    this.setState({ value: value });
  },

  render: function() {
    return (
      <div>
        <InnerComponent value={this.state.value} />
        <a onClick={this.onClick}>Click me</a>
      </div>
    );
  }
});

প্রথম বারের অভ্যন্তরীণ উপাদানটি রেন্ডার হয়ে গেলে এর মান প্রাপ হিসাবে এটিতে {foo: 'বার' থাকবে। যদি ব্যবহারকারী অ্যাঙ্কারে ক্লিক করে তবে পিতামাতার উপাদানগুলির অবস্থাটি {মান: {foo: 'বারবার'}} এ আপডেট হবে, যা অভ্যন্তরীণ উপাদানটির পুনরায় রেন্ডারিং প্রক্রিয়াটিকে ট্রিগার করবে, যা {foo: 'বারবার' হিসাবে পাবেন প্রোপ জন্য নতুন মান

সমস্যাটি হ'ল যেহেতু পিতামাতা এবং অভ্যন্তরীণ উপাদানগুলি একই বস্তুর সাথে একটি রেফারেন্স ভাগ করে দেয়, যখন বস্তুটি অনক্লিক ফাংশনের 2 লাইনটিতে রূপান্তরিত হয়, তখন অভ্যন্তরের উপাদানটির প্রপটি পরিবর্তিত হবে। সুতরাং, যখন পুনরায় রেন্ডারিং প্রক্রিয়া শুরু হবে এবং কম্পোনেন্ট আপডেটটি আহ্বান করা উচিত, this.prop.value.foo NextProp.value.foo এর সমান হবে, কারণ বাস্তবে, এই.প্রোপস.ভ্যালু পরবর্তী পপস.ভ্যালু হিসাবে একই বস্তুর উল্লেখ করে।

ফলস্বরূপ, যেহেতু আমরা প্রোপ এবং শর্ট সার্কিটের পুনরায় রেন্ডারিংয়ের প্রক্রিয়াটি পরিবর্তন করব, তাই ইউআই 'বার' থেকে 'বার্বারে' আপডেট হবে না


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