প্রতিক্রিয়াতে কীভাবে সন্তানের রাষ্ট্র অ্যাক্সেস করবেন?


214

আমার নিম্নলিখিত কাঠামো রয়েছে:

FormEditor- একাধিক FieldEditor ধারণ করে FieldEditor- ফর্মের একটি ক্ষেত্র সম্পাদনা করে এবং এটি সম্পর্কিত বিভিন্ন মান সংরক্ষণ করে

ফর্মএডিটরের মধ্যে যখন একটি বোতাম ক্লিক করা হয়, তখন আমি ক্ষেত্র সম্পর্কে সমস্ত FieldEditorউপাদানগুলি থেকে , তাদের রাজ্যে থাকা তথ্যগুলি সংগ্রহ করতে এবং ফর্মএডিটারের মধ্যে সমস্ত কিছু রাখতে সক্ষম হতে চাই।

আমি ক্ষেত্রগুলি সম্পর্কিত তথ্য FieldEditorরাজ্যের বাইরে সংরক্ষণের জন্য বিবেচনা করেছি এবং FormEditorপরিবর্তে এটির রাজ্যে রেখেছি । যাইহোক, FormEditorএটির FieldEditorপরিবর্তনের জন্য এবং তার তথ্যের স্থিতিস্থানে সংরক্ষণ করার সাথে সাথে এর প্রতিটি উপাদান শুনতে হবে।

আমি কি পরিবর্তে কেবল বাচ্চাদের রাজ্যে প্রবেশ করতে পারি না? এটা আদর্শ?


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

@ ফেলিক্সক্লিং তারপরে আপনি পরামর্শ দিচ্ছেন যে সন্তানের পিতামাতার যোগাযোগের আদর্শ উপায়টি কেবল ইভেন্টগুলি?
মোশে রেভাঃ

3
হ্যাঁ, ঘটনাগুলি একটি উপায়। অথবা ফ্লক্সের প্রচারের মতো একটি দিকনির্দেশক ডেটা প্রবাহ রয়েছে: ফেসবুক.
github.io/flux

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

4
আমি মনে করি প্রতিক্রিয়া ডক্স 'লিফটিং স্টেট আপ' সম্ভবত এটি করার সবচেয়ে 'র্যাক্টি' উপায়
আইসিসি

উত্তর:


135

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

এর রেখা বরাবর কিছু সম্ভবত:

const FieldEditor = ({ value, onChange, id }) => {
  const handleChange = event => {
    const text = event.target.value;
    onChange(id, text);
  };

  return (
    <div className="field-editor">
      <input onChange={handleChange} value={value} />
    </div>
  );
};

const FormEditor = props => {
  const [values, setValues] = useState({});
  const handleFieldChange = (fieldId, value) => {
    setValues({ ...values, [fieldId]: value });
  };

  const fields = props.fields.map(field => (
    <FieldEditor
      key={field}
      id={field}
      onChange={handleFieldChange}
      value={values[field]}
    />
  ));

  return (
    <div>
      {fields}
      <pre>{JSON.stringify(values, null, 2)}</pre>
    </div>
  );
};

// To add abillity to dynamically add/remove fields keep the list in state
const App = () => {
  const fields = ["field1", "field2", "anotherField"];

  return <FormEditor fields={fields} />;
};

আসল - প্রাক-হুক সংস্করণ:


2
এটি অন চেঞ্জের জন্য দরকারী তবে অনসামিতের ক্ষেত্রে তেমনটি নয়।
190290000 রুবল ম্যান

1
@ 190290000 রুবেলমান আপনি কী বলতে চাইছেন তা আমি নিশ্চিত নই, তবে যেহেতু স্বতন্ত্র ক্ষেত্রগুলিতে অন চেঞ্জ হ্যান্ডলারগুলি আপনার ফর্মএডিটর উপাদানটিতে আপনার রাজ্যে সর্বদা সম্পূর্ণ ফর্ম ডেটা উপলব্ধ রয়েছে তা নিশ্চিত করে রাখে, আপনার অনসামিতটি ঠিক এর মতো কিছু অন্তর্ভুক্ত করবে myAPI.SaveStuff(this.state);। আপনি যদি আরও কিছুটা বিশদভাবে বর্ণনা করেন তবে সম্ভবত আমি আপনাকে আরও ভাল উত্তর দিতে পারি :)
মার্কাস-ইপ্স

বলুন আমার কাছে একটি ফর্ম রয়েছে বিভিন্ন ধরণের 3 টি ক্ষেত্র, যার প্রতিটি নিজস্ব বৈধতা রয়েছে। জমা দেওয়ার আগে আমি তাদের প্রত্যেককে বৈধতা দিতে চাই। যদি বৈধতা ব্যর্থ হয়, ত্রুটিযুক্ত প্রতিটি ক্ষেত্রের পুনরায় রেন্ডার করা উচিত। আপনার প্রস্তাবিত সমাধান দিয়ে এটি কীভাবে করব তা আমি খুঁজে পাইনি, তবে সম্ভবত একটি উপায় আছে!
190290000 রুবেল ম্যান

1
@ 190290000 রুবেলমন মূল প্রশ্নের চেয়ে আলাদা কেস বলে মনে হচ্ছে। আরও বিশদ এবং সম্ভবত কিছু নমুনা কোড সহ একটি নতুন প্রশ্ন খুলুন, এবং আমি পরে একবার দেখতে পারি :)
মার্কাস-ইপ্স

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

189

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

আপনি যদি সত্যিই কোনও উপাদানগুলির বাচ্চাদের অবস্থা অ্যাক্সেস করতে চান তবে refআপনি প্রতিটি সন্তানের কাছে ডাকা একটি সম্পত্তি অর্পণ করতে পারেন । রেফারেন্সগুলি বাস্তবায়নের দুটি উপায় রয়েছে: ব্যবহার React.createRef()এবং কলব্যাক রেফগুলি।

ব্যবহার React.createRef()

প্রতিক্রিয়া 16.3 এর হিসাবে রেফারেন্সগুলি ব্যবহার করার জন্য এটি বর্তমানে প্রস্তাবিত উপায় ( আরও তথ্যের জন্য ডক্স দেখুন )। আপনি যদি পূর্ববর্তী সংস্করণ ব্যবহার করে থাকেন তবে নীচে কলব্যাকের রেফারেন্সগুলি দেখুন।

আপনার প্যারেন্ট উপাদানটির কনস্ট্রাক্টরে আপনাকে একটি নতুন রেফারেন্স তৈরি করতে হবে এবং তারপরে refএট্রিবিউটের মাধ্যমে এটি কোনও সন্তানের কাছে অর্পণ করতে হবে ।

class FormEditor extends React.Component {
  constructor(props) {
    super(props);
    this.FieldEditor1 = React.createRef();
  }
  render() {
    return <FieldEditor ref={this.FieldEditor1} />;
  }
}

এই ধরণের রেফ অ্যাক্সেস করতে আপনার ব্যবহার করতে হবে:

const currentFieldEditor1 = this.FieldEditor1.current;

এটি মাউন্ট করা উপাদানটির একটি উদাহরণ ফিরিয়ে দেবে যাতে আপনি তারপরে currentFieldEditor1.stateরাজ্যে অ্যাক্সেস ব্যবহার করতে পারেন।

কেবলমাত্র একটি द्रुत নোট বলার জন্য যে আপনি যদি এই রেফারেন্সগুলি কোনও উপাদান (উদাহরণস্বরূপ <div ref={this.divRef} />) এর পরিবর্তে কোনও ডিওএম নোডে ব্যবহার করেন তবে this.divRef.currentকোনও উপাদানগুলির উদাহরণের পরিবর্তে অন্তর্নিহিত DOM উপাদানটি ফিরিয়ে দেবেন।

কলব্যাক রেফারেন্স

এই সম্পত্তিটি একটি কলব্যাক ফাংশন নেয় যা সংযুক্ত উপাদানটির জন্য একটি রেফারেন্স পাস করা হয়। এই কলব্যাকটি উপাদানটি মাউন্ট করা বা আনমাউন্ট করার সাথে সাথেই কার্যকর করা হয়।

উদাহরণ স্বরূপ:

<FieldEditor
    ref={(fieldEditor1) => {this.fieldEditor1 = fieldEditor1;}
    {...props}
/>

এই উদাহরণগুলিতে রেফারেন্সটি প্যারেন্ট উপাদানগুলিতে সংরক্ষণ করা হয়। আপনার কোডটিতে এই উপাদানটি কল করতে, আপনি ব্যবহার করতে পারেন:

this.fieldEditor1

এবং তারপরে this.fieldEditor1.stateরাষ্ট্রটি পেতে ব্যবহার করুন ।

একটি বিষয় লক্ষণীয়, নিশ্চিত করুন যে আপনি আপনার সন্তানের উপাদানটি অ্যাক্সেস করার আগে it _ ^ অ্যাক্সেস করার আগে রেন্ডার হয়েছে ^

উপরের মতো, আপনি যদি এই রেফারেন্সগুলি কোনও উপাদান (উদাহরণস্বরূপ <div ref={(divRef) => {this.myDiv = divRef;}} />) এর পরিবর্তে কোনও ডিওএম নোডে ব্যবহার করেন তবে this.divRefকোনও উপাদানগুলির উদাহরণের পরিবর্তে অন্তর্নিহিত DOM উপাদানটি ফিরিয়ে দেবেন।

আরো তথ্য

আপনি যদি রিঅ্যাক্টের রেফার সম্পত্তি সম্পর্কে আরও জানতে চান তবে ফেসবুক থেকে এই পৃষ্ঠাটি দেখুন

নিশ্চিত হয়ে নিন যে আপনি " ডোন্ট ওভার ইউজ রেফস " বিভাগটি পড়েছেন যা বলে যে আপনার সন্তানের ব্যবহার state"জিনিসগুলি ঘটানোর জন্য" করা উচিত নয় ।

আশা করি এটি ^ _ ^ সহায়তা করবে ^

সম্পাদনা করুন: React.createRef()রেফ তৈরির জন্য যুক্ত পদ্ধতি। ES5 কোড সরানো হয়েছে।


5
ঝরঝরে সামান্য জোয়ার, আপনি ফাংশন থেকে কল করতে পারেন this.refs.yourComponentNameHere। আমি ফাংশনগুলির মাধ্যমে রাষ্ট্র পরিবর্তন করার জন্য এটি দরকারী বলে মনে করেছি। উদাহরণ: this.refs.textInputField.clearInput();
ডিলান পিয়ার্স

7
সাবধান (দস্তাবেজগুলি থেকে): রেফস একটি নির্দিষ্ট সন্তানের কাছে কোনও বার্তা পাঠানোর দুর্দান্ত উপায় যা এমনভাবে স্ট্রিমিং রিঅ্যাকটিভ propsএবং এর মাধ্যমে স্ট্রিমিংয়ের জন্য অসুবিধাজনক হবে না state। আপনার অ্যাপ্লিকেশনটির মাধ্যমে প্রবাহিত ডেটার জন্য এগুলি আপনার গোপনে থাকা বিমূর্ততা হওয়া উচিত নয়। ডিফল্টরূপে, প্রতিক্রিয়াশীল ডেটা প্রবাহ ব্যবহার করুন এবং refঅন্তর্নিহিতভাবে অ-প্রতিক্রিয়াশীল এমন ক্ষেত্রে ব্যবহারের জন্য সংরক্ষণ করুন ।
লিন

2
আমি কেবলমাত্র সেই রাজ্য পাই যা নির্মাতার অভ্যন্তরে সংজ্ঞায়িত হয়েছিল (তারিখের রাজ্য নয়)
ভ্লাদো পান্ডিয়

3
রেফ ব্যবহার করে এখন ' নিয়ন্ত্রিত উপাদানগুলি ' ব্যবহারের সুপারিশের সাথে 'নিয়ন্ত্রিত উপাদানগুলি' হিসাবে
শ্রেণিবদ্ধ করা হয়েছে

যদি সন্তানের উপাদানটি একটি Redux connectedউপাদান হয় তবে এটি করা সম্ভব ?
jmancherje

7

এটির 2020 এবং আপনার প্রচুর পরিমাণে এখানে একই ধরণের সমাধানের সন্ধান করা হবে তবে হুক্সের সাথে (তারা দুর্দান্ত!) এবং কোড সাফাই এবং সিনট্যাক্সের ক্ষেত্রে সর্বশেষ পদ্ধতির সাথে।

পূর্ববর্তী উত্তরগুলি যেমন বলেছিল, এই ধরণের সমস্যার সর্বোত্তম পন্থা হ'ল রাষ্ট্রকে শিশু উপাদানগুলির বাইরে রাখা fieldEditor। আপনি একাধিক উপায়ে এটি করতে পারেন।

সর্বাধিক "জটিল" হ'ল বৈশ্বিক প্রসঙ্গে (রাষ্ট্র) যা পিতামাতা এবং শিশু উভয়ই অ্যাক্সেস এবং সংশোধন করতে পারে। গাছের শ্রেণিবিন্যাসের উপাদানগুলি খুব গভীর এবং এটি প্রতিটি স্তরে প্রপস পাঠাতে ব্যয়বহুল হয় যখন এটি একটি দুর্দান্ত সমাধান।

এই ক্ষেত্রে আমি মনে করি এটির পক্ষে এটি উপযুক্ত নয়, এবং আরও সহজ পদ্ধতির সাহায্যে কেবলমাত্র শক্তিশালী ব্যবহার করে আমরা আমাদের ফলাফল পেতে চাই React.useState()

ক্লাস উপাদানগুলির তুলনায় সহজতর, রিঅ্যাক্ট.উজস্টেট () হুকের সাথে যোগাযোগ করুন

যেমনটি বলা হয়েছে আমরা পরিবর্তনগুলি মোকাবেলা করব এবং আমাদের সন্তানের উপাদানগুলির ডেটা fieldEditorআমাদের পিতামাতার মধ্যে সংরক্ষণ করব fieldForm। এটি করার জন্য আমরা সেই কার্যটির জন্য একটি রেফারেন্স প্রেরণ করব যা এই fieldFormরাজ্যে পরিবর্তনগুলি ডিল করবে এবং প্রয়োগ করবে , আপনি এটি দিয়ে করতে পারেন:

function FieldForm({ fields }) {
  const [fieldsValues, setFieldsValues] = React.useState({});
  const handleChange = (event, fieldId) => {
    let newFields = { ...fieldsValues };
    newFields[fieldId] = event.target.value;

    setFieldsValues(newFields);
  };

  return (
    <div>
      {fields.map(field => (
        <FieldEditor
          key={field}
          id={field}
          handleChange={handleChange}
          value={fieldsValues[field]}
        />
      ))}
      <div>{JSON.stringify(fieldsValues)}</div>
    </div>
  );
}

দ্রষ্টব্য যে React.useState({})কলটি 0-তে নির্দিষ্ট হওয়া মান (এই ক্ষেত্রে খালি অবজেক্ট) এবং অবস্থান 1 এর সাথে মানটিকে সংশোধনকারী ফাংশনের রেফারেন্স সহ একটি অ্যারে প্রদান করবে।

এখন সন্তানের উপাদান সহ FieldEditor, আপনার এমনকি কোনও রিটার্ন স্টেটমেন্ট সহ কোনও ফাংশন তৈরি করার প্রয়োজন নেই, একটি তীর ফাংশন সহ একটি চর্বিহীন ধ্রুবকটি করবে!

const FieldEditor = ({ id, value, handleChange }) => (
  <div className="field-editor">
    <input onChange={event => handleChange(event, id)} value={value} />
  </div>
);

Aaaaand আমরা সম্পন্ন করেছি, আরও কিছুই নয়, কেবলমাত্র এই দুটি পাতলা ফাংশনাল উপাদানগুলির সাথে আমাদের শেষ লক্ষ্যটি রয়েছে আমাদের সন্তানের FieldEditorমান "অ্যাক্সেস" এবং এটি আমাদের পিতামাতাকে প্রদর্শন করে।

আপনি 5 বছর আগে থেকে গৃহীত উত্তরটি যাচাই করতে পারেন এবং দেখুন যে কীভাবে হুকস প্রতিক্রিয়ার কোড লাইনার তৈরি করেছিল (প্রচুর পরিমাণে!)।

আশা করি আমার উত্তর আপনাকে হুকস সম্পর্কে আরও জানতে এবং বুঝতে সহায়তা করে এবং আপনি যদি একটি কার্যকারী উদাহরণটি পরীক্ষা করতে চান তবে এটি এখানে


4

এখন আপনি ইনপুটফিল্ডের স্টেটটি অ্যাক্সেস করতে পারবেন যা ফর্মএডিটারের সন্তান।

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

বাটনে ক্লিক করুন আমরা কেবল ইনপুট ক্ষেত্রগুলির রাজ্য মুদ্রণ করছি।

এখানে মূল বক্তব্যটি হ'ল আমরা প্রপসগুলি ইনপুট ফিল্ডের আইডি / মান পেতে এবং ইনপুট ফিল্ডে বৈশিষ্ট্য হিসাবে নির্ধারিত ফাংশনগুলিকে কল করতে যখন আমরা পুনরায় ব্যবহারযোগ্য শিশু ইনপুট ক্ষেত্র তৈরি করতে পারি তখনও তা কল করতে পারি।

class InputField extends React.Component{
  handleChange = (event)=> {
    const val = event.target.value;
    this.props.onChange(this.props.id , val);
  }

  render() {
    return(
      <div>
        <input type="text" onChange={this.handleChange} value={this.props.value}/>
        <br/><br/>
      </div>
    );
  }
}       


class FormEditorParent extends React.Component {
  state = {};
  handleFieldChange = (inputFieldId , inputFieldValue) => {
    this.setState({[inputFieldId]:inputFieldValue});
  }
  //on Button click simply get the state of the input field
  handleClick = ()=>{
    console.log(JSON.stringify(this.state));
  }

  render() {
    const fields = this.props.fields.map(field => (
      <InputField
        key={field}
        id={field}
        onChange={this.handleFieldChange}
        value={this.state[field]}
      />
    ));

    return (
      <div>
        <div>
          <button onClick={this.handleClick}>Click Me</button>
        </div>
        <div>
          {fields}
        </div>
      </div>
    );
  }
}

const App = () => {
  const fields = ["field1", "field2", "anotherField"];
  return <FormEditorParent fields={fields} />;
};

ReactDOM.render(<App/>, mountNode);

7
নিশ্চিত না যে আমি এইটিকে উজ্জীবিত করতে পারি। আপনি এখানে এমন কী উল্লেখ করবেন যা ইতিমধ্যে @ মার্কাস-আইপিএস দ্বারা উত্তর দেওয়া হয়নি?
আলেকজান্ডার বার্ড

3

পূর্ববর্তী উত্তরগুলি যেমন বলেছে, রাষ্ট্রটিকে একটি শীর্ষ উপাদানগুলিতে নিয়ে যাওয়ার চেষ্টা করুন এবং তার বাচ্চাদের হাতে কলব্যাকের মাধ্যমে রাজ্যকে সংশোধন করার চেষ্টা করুন।

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

নিম্নলিখিত উদাহরণটি একবার দেখুন:

const Parent = () => {
    const myRef = useRef();
    return <Child ref={myRef} />;
}

const Child = React.forwardRef((props, ref) => {
    const [myState, setMyState] = useState('This is my state!');
    useImperativeHandle(ref, () => ({getMyState: () => {return myState}}), [myState]);
})

তারপরে আপনি কল করে পিতা বা মাতা উপাদানটিতে মাইস্টেট পেতে সক্ষম হবেন: myRef.current.getMyState();

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