প্রতিক্রিয়া ফর্মের প্রপস পরিবর্তন সম্পর্কে রাষ্ট্র আপডেট করে


184

একটি প্রতিক্রিয়া ফর্ম নিয়ে এবং রাজ্যটি সঠিকভাবে পরিচালনা করতে আমার সমস্যা হচ্ছে। আমার একটি ফর্মের একটি টাইম ইনপুট ক্ষেত্র রয়েছে (একটি মডেলে)। প্রাথমিক মানটি একটি রাজ্যের ভেরিয়েবল হিসাবে সেট করা থাকে getInitialStateএবং এটি প্যারেন্ট উপাদান থেকে পাস করা হয়। এটি নিজেই সূক্ষ্মভাবে কাজ করে।

আমি যখন প্যারেন্ট উপাদানগুলির মাধ্যমে ডিফল্ট স্টার্টটাইম মান আপডেট করতে চাই তখন সমস্যাটি আসে। আপডেট নিজেই মাধ্যমে প্যারেন্ট উপাদান হয় setState start_time: new_time। তবে আমার ফর্মটিতে, ডিফল্ট স্টার্টটাইম মানটি কখনই পরিবর্তন হয় না, কারণ এটি কেবল একবার অন্তর্ভুক্ত করা হয় getInitialState

আমি componentWillUpdateরাষ্ট্রের পরিবর্তনের জন্য জোর করে ব্যবহার করার চেষ্টা করেছি setState start_time: next_props.start_time, যা আসলে কাজ করেছিল তবে আমাকে Uncaught RangeError: Maximum call stack size exceededত্রুটি দিয়েছে ।

সুতরাং আমার প্রশ্নটি হল, এই ক্ষেত্রে রাষ্ট্র আপডেট করার সঠিক উপায় কী? আমি কি এই ভুল সম্পর্কে কোনওভাবে ভাবছি?

বর্তমান কোড:

@ModalBody = React.createClass
  getInitialState: ->
    start_time: @props.start_time.format("HH:mm")

  #works but takes long and causes:
  #"Uncaught RangeError: Maximum call stack size exceeded"
  componentWillUpdate: (next_props, next_state) ->
    @setState(start_time: next_props.start_time.format("HH:mm"))

  fieldChanged: (fieldName, event) ->
    stateUpdate = {}
    stateUpdate[fieldName] = event.target.value
    @setState(stateUpdate)

  render: ->
    React.DOM.div
      className: "modal-body"
      React.DOM.form null,
        React.createElement FormLabelInputField,
          type: "time"
          id: "start_time"
          label_name: "Start Time"
          value: @state.start_time
          onChange: @fieldChanged.bind(null, "start_time”)

@FormLabelInputField = React.createClass
  render: ->
    React.DOM.div
      className: "form-group"
      React.DOM.label
        htmlFor: @props.id
        @props.label_name + ": "
      React.DOM.input
        className: "form-control"
        type: @props.type
        id: @props.id
        value: @props.value
        onChange: @props.onChange

উত্তর:


287

উপাদানযুক্তউলআরসিপপ্রপুলগুলি 16 প্রতিক্রিয়া দেখানোর পর থেকে বঞ্চিত হয়েছে: পরিবর্তে getDeridedStateFromProp ব্যবহার করুন

যদি আমি সঠিকভাবে বুঝতে পারি, আপনার একটি পিতামাত উপাদান রয়েছে যা start_timeসেই ModalBodyউপাদানটিতে চলে যাচ্ছে যা এটিকে তার নিজের রাজ্যে নির্ধারণ করে? এবং আপনি সেই সময়টি কোনও সন্তানের উপাদান নয়, পিতামাতার কাছ থেকে আপডেট করতে চান।

প্রতিক্রিয়াটির সাথে এই দৃশ্যটি মোকাবেলা করার জন্য কিছু টিপস রয়েছে। (দ্রষ্টব্য, এটি একটি পুরানো নিবন্ধ যা এরপরে ওয়েব থেকে সরানো হয়েছে component উপাদান প্রপসের বর্তমান দস্তাবেজের একটি লিঙ্ক এখানে )।

রাজ্য উত্পন্ন করতে প্রপস ব্যবহার করা getInitialStateপ্রায়শই "সত্যের উত্স" এর সদৃশ হয়, যেখানে আসল তথ্য থাকে। কারণ getInitialStateকেবলমাত্র যখন উপাদানটি প্রথম তৈরি করা হয় কেবল তখনই অনুরোধ করা হয়।

যখনই সম্ভব, অন-ফ্লাইয়ে মানগুলি গণনা করুন যাতে তারা পরবর্তী সময়ে সিঙ্ক থেকে বেরিয়ে না যায় এবং রক্ষণাবেক্ষণের সমস্যা সৃষ্টি করে।

মূলত, আপনি যখনই propsকোনও সন্তানের কাছে পিতামাতার দায়িত্ব অর্পণ করেন তখন stateসবসময় প্রোপ আপডেটে ডাকা হয় না। componentWillReceivePropsপদ্ধতিটি ব্যবহার করে আপনাকে এটিকে ম্যানুয়ালি আহ্বান করতে হবে ।

componentWillReceiveProps(nextProps) {
  // You don't have to do this check first, but it can help prevent an unneeded render
  if (nextProps.startTime !== this.state.startTime) {
    this.setState({ startTime: nextProps.startTime });
  }
}

83
অননুমোদিত হিসাবে প্রতিক্রিয়া 16
শহরবাসী

7
@ ডুড এটি এখনও অবহেলিত নয়, আপনি যা উল্লেখ করেন তা ভবিষ্যতের রেফারেন্সের জন্য কেবল একটি শীর্ষস্থানীয়। আমি উদ্ধৃতি দিয়েছি[..]going to be deprecated in the future
প্যাডটটক

7
@poepje এটি এখনও অবহেলিত হতে পারে না তবে এটি বর্তমান মানদণ্ডের দ্বারা অনিরাপদ হিসাবে দেখেছে এবং সম্ভবত এড়ানো উচিত
অনুমান করা হয়েছে

12
সুতরাং, কম্পোনেন্টবিলিপিপ্রোপস অবমূল্যায়নের পরে এটি করার নতুন উপায়টি কী হওয়া উচিত?
বরিস ডি তেওহরভ

4
@ বোরিস এখন প্রতিক্রিয়াশীল দলটি মূলত আপনাকে স্টাফ করতে বলছে। তারা আপনাকে একটি নতুন পদ্ধতি দেয়, যার নাম getDerivedStateFromProp। ক্যাচ হচ্ছে এটি একটি স্থির পদ্ধতি। অর্থ আপনি রাষ্ট্র আপডেট করার জন্য অ্যাসিঙ্ক্রোনাস কিছু করতে পারবেন না (কারণ আপনাকে তাত্ক্ষণিকভাবে নতুন রাষ্ট্র ফিরিয়ে দিতে হবে), না আপনি শ্রেণিক পদ্ধতি বা ক্ষেত্রগুলি অ্যাক্সেস করতে পারবেন না। আপনি স্মৃতিচারণও ব্যবহার করতে পারেন তবে এটি প্রতিটি ব্যবহারের ক্ষেত্রে খাপ খায় না। আবারও, প্রতিক্রিয়াশীল দলগুলি তাদের কাজ করার পদ্ধতিটিকে জোর করে চাপিয়ে দিতে চায়। এটি একটি অত্যন্ত বোকা এবং অক্ষম নকশার সিদ্ধান্ত।
ig-dev

76

স্পষ্টতই জিনিসগুলি পরিবর্তন হচ্ছে .... getDeridedStateFromProp () এখন পছন্দসই ফাংশন।

class Component extends React.Component {
  static getDerivedStateFromProps(props, current_state) {
    if (current_state.value !== props.value) {
      return {
        value: props.value,
        computed_prop: heavy_computation(props.value)
      }
    }
    return null
  }
}

(উপরের কোড ডানবুরজো @ গিথুব)


7
এফওয়াইআই, nullreturn null
আপনাকেও

@ ইলজিটওয়াল্ডারম - 4 জন আপনার মন্তব্যকে সমর্থন জানিয়ে কোড সম্পাদনা করেছেন - এটি কি আসলেই কোনও পার্থক্য করে?
এরিচবিএসচুল্জ

একটি দুর্দান্ত ভাল সংস্থান রয়েছে যা বিভিন্ন বিকল্পের গভীরতার সাথে যায় এবং আপনি কেন getDerivedStateFromPropsবা মেমোয়াইজেশন
অবলম্বন

2
getDeridedStateFromProp স্থিতিশীল হতে বাধ্য করা হয়। অর্থ আপনি রাষ্ট্র আপডেট করার জন্য অ্যাসিঙ্ক্রোনাস কিছুই করতে পারবেন না, আপনি ক্লাসের পদ্ধতি বা ক্ষেত্রগুলিও অ্যাক্সেস করতে পারবেন না। আবারও, প্রতিক্রিয়াশীল দলগুলি তাদের কাজ করার পদ্ধতিটিকে জোর করে চাপিয়ে দিতে চায়। এটি একটি অত্যন্ত বোকা এবং অক্ষম নকশার সিদ্ধান্ত।
ig-dev

39

componentWillReceiveProps অবচিত করা হচ্ছে কারণ এটি ব্যবহার করে "প্রায়শই বাগ এবং অসঙ্গতি হয়"।

যদি বাইরে থেকে কিছু পরিবর্তন হয় তবে পুরোপুরি সাথে সন্তানের উপাদানটি পুনরায় সেট করতে বিবেচনা করুনkey

keyসন্তানের উপাদানগুলির জন্য একটি সরবরাহ সরবরাহ নিশ্চিত করে যে যখনই keyবাইরে থেকে পরিবর্তনের মান আসে তখন এই উপাদানটি পুনরায় রেন্ডার হয়। যেমন,

<EmailInput
  defaultEmail={this.props.user.email}
  key={this.props.user.id}
/>

এর অভিনয় সম্পর্কে:

যদিও এটি ধীরে ধীরে শোনাচ্ছে, পারফরম্যান্সের পার্থক্যটি সাধারণত তুচ্ছ। কীগুলি ব্যবহার করা এমনকি দ্রুততর হতে পারে যদি উপাদানগুলিতে ভারী যুক্তি থাকে যা আপডেটগুলিতে চলে since


1
চাবি, গোপন! উপরে উল্লিখিত হিসাবে 16 প্রতিক্রিয়াতে পুরোপুরি কাজ করে
ড্যারেন সুইভিনে

কীটি কাজ করবে না, যদি এটি কোনও অবজেক্ট হয় এবং আপনার কোনও অনন্য স্ট্রিং না থাকে
ব্যবহারকারীর 3468806

কী বস্তুর জন্য কাজ করে, আমি এটি করেছি। অবশ্যই আমি কী জন্য একটি অনন্য স্ট্রিং ছিল।
tsujp

@ ব্যবহারকারী 3468806 যদি এটি বাহ্যিক রেফারেন্স সহ কোনও জটিল অবজেক্ট না হয় তবে আপনি নিজের অবজেক্ট JSON.stringify(myObject)থেকে একটি অনন্য কী অর্জন করতে পারেন ।
রায় প্রিন্স

24

রয়েছে componentDidUpdate পাওয়া যায়।

ফাংশন স্বাক্ষরকারী:

componentDidUpdate(prevProps, prevState, snapshot)

উপাদানটি আপডেট হয়ে গেলে DOM এ পরিচালনা করার সুযোগ হিসাবে এটি ব্যবহার করুন। প্রাথমিক দিকে ডাকা হয় নাrender

দেখুন আপনি সম্ভবত রাজ্য উদ্ভূত প্রয়োজন হবে না ধারা, যা উভয়ের জন্য এন্টি-প্যাটার্ন বর্ণনা componentDidUpdateএবং getDerivedStateFromProps। আমি এটি খুব দরকারী খুঁজে পেয়েছি।


আমি ব্যবহারটি শেষ করি componentDidUpdateকারণ এটি সহজ এবং এটি বেশিরভাগ ক্ষেত্রেই বেশি উপযুক্ত।
কিটেলডোগ

14

এটি করার নতুন হুক উপায় হ'ল পুরাতন পদ্ধতিতে কম্পোনেন্ট উইল রিসিপপ্রসেসের পরিবর্তে UseEffect ব্যবহার করা:

componentWillReceiveProps(nextProps) {
  // You don't have to do this check first, but it can help prevent an unneeded render
  if (nextProps.startTime !== this.state.startTime) {
    this.setState({ startTime: nextProps.startTime });
  }
}

ক্রিয়ামূলক হুক্স চালিত উপাদানগুলিতে নিম্নলিখিত হয়ে যায়:

// store the startTime prop in local state
const [startTime, setStartTime] = useState(props.startTime)
// 
useEffect(() => {
  if (props.startTime !== startTime) {
    setStartTime(props.startTime);
  }
}, [props.startTime]);

আমরা সেটস্টেট ব্যবহার করে রাষ্ট্রটি সেট করি, ব্যবহারের প্রভাব ব্যবহার করে আমরা নির্দিষ্ট প্রপটিতে পরিবর্তনগুলি পরীক্ষা করি এবং প্রপ পরিবর্তনের ক্ষেত্রে রাষ্ট্র আপডেট করার জন্য পদক্ষেপ গ্রহণ করি।


5

আপনার সম্ভবত ডেরাইভড স্টেটের দরকার নেই

1. পিতামাতার কাছ থেকে একটি কী সেট করুন

যখন কোনও কী পরিবর্তন হয়, প্রতিক্রিয়া বর্তমানকে আপডেট করার পরিবর্তে একটি নতুন উপাদান তৈরি করবে। কীগুলি সাধারণত গতিশীল তালিকার জন্য ব্যবহৃত হয় তবে এটি এখানে দরকারী useful

2. ব্যবহার getDerivedStateFromProps/componentWillReceiveProps

যদি কোনও কারণে কীটি কাজ না করে (সম্ভবত উপাদানটি আরম্ভ করার জন্য খুব ব্যয়বহুল)

ব্যবহার করে getDerivedStateFromPropsআপনি রাজ্যের যে কোনও অংশ পুনরায় সেট করতে পারেন তবে এই মুহুর্তে এটি কিছুটা বগি বলে মনে হচ্ছে (v16.7)! ব্যবহারের জন্য উপরের লিঙ্কটি দেখুন


2

প্রতিক্রিয়া নথি থেকে: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-deriv-state.html

যখন প্রপস পরিবর্তন হয় তখন একটি অ্যান্টি প্যাটার্ন হ'ল রাজ্য মুছে ফেলা

প্রতিক্রিয়া 16, যেহেতু উপাদানবিহীনগ্রাহীপ্রপোস হ্রাস করা হয়েছে। প্রতিক্রিয়া নথি থেকে, এক্ষেত্রে প্রস্তাবিত পদ্ধতির ব্যবহার

  1. সম্পূর্ণ উপাদান নিয়ন্ত্রিত: ParentComponentএর ModalBodyমালিক হবেন start_timeরাষ্ট্র। এটি এই ক্ষেত্রে আমার পছন্দসই পদ্ধতি নয়, কারণ আমি মনে করি মডেলের এই রাষ্ট্রের মালিক হওয়া উচিত।
  2. একটি কী সহ পুরোপুরি অনিয়ন্ত্রিত উপাদান: এটি আমার পছন্দের পদ্ধতির। থেকে একটি উদাহরণ ডকুমেন্টেশন প্রতিক্রিয়া https://codesandbox.io/s/6v1znlxyxn । আপনি ইতিমধ্যে নিজের মতো করে সম্পূর্ণরূপে start_timeরাষ্ট্রের মালিক হন ModalBodyএবং ব্যবহার করবেন getInitialStatestart_timeরাষ্ট্রটি পুনরায় সেট করতে , আপনি কেবলমাত্র থেকে কীটি পরিবর্তন করুনParentComponent


0

মেমোইজ ব্যবহার করুন

অপেশনের রাজ্যের ডেরাইভেশন হ'ল প্রপসের সরাসরি হেরফের, যার সত্যিকারের ডাইরাইভেশন প্রয়োজন হয় না। অন্য কথায়, আপনার কাছে যদি এমন কোনও প্রপ থাকে যা সরাসরি ব্যবহার বা রূপান্তরিত হতে পারে তবে প্রপাকে স্টেটে সংরক্ষণ করার দরকার নেই

প্রদত্ত রাষ্ট্রের মানটি start_timeকেবল উত্স হিসাবে দেওয়া হয় start_time.format("HH:mm"), প্রোপটিতে থাকা তথ্য ইতিমধ্যে উপাদানটি আপডেট করার জন্য যথেষ্ট।

তবে আপনি যদি কেবল কোনও প্রোপ পরিবর্তনে কল করতে চান তবে সর্বশেষ ডকুমেন্টেশন অনুসারে এটি করার সঠিক উপায়টি মেমোয়েজের মাধ্যমে হবে: https://reactjs.org/blog/2018/06/07/you-probably-dont- প্রয়োজন ডিরাইভড-state.html # কি-সম্পর্কে-memoization


-1

আমি মনে করি ব্যবহারের রেফটি আমার জন্য নিরাপদ, উপরের কোনও পদ্ধতি সম্পর্কে যত্নের প্রয়োজন নেই।

class Company extends XComponent {
    constructor(props) {
        super(props);
        this.data = {};
    }
    fetchData(data) {
        this.resetState(data);
    }
    render() {
        return (
            <Input ref={c => this.data['name'] = c} type="text" className="form-control" />
        );
    }
}
class XComponent extends Component {
    resetState(obj) {
        for (var property in obj) {
            if (obj.hasOwnProperty(property) && typeof this.data[property] !== 'undefined') {
                if ( obj[property] !== this.data[property].state.value )
                    this.data[property].setState({value: obj[property]});
                else continue;
            }
            continue;
        }
    }
}

আমি মনে করি এই প্রতিক্রিয়াটি ক্রিপ্টিক (কোডটি খুব সহজেই পঠনযোগ্য এবং কোনও ব্যাখ্যা ছাড়াই বা ওপির সমস্যার সাথে যুক্ত নয়) এবং ওপি'র সমস্যাটিকে মোকাবেলা করে না, এটি কীভাবে প্রাথমিক অবস্থায় পরিচালনা করতে হয়।
নেটচকিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.