প্রতিক্রিয়াতে সেটস্টেট সহ কোনও অবজেক্ট আপডেট করা হচ্ছে


265

এর সাথে অবজেক্টের বৈশিষ্ট্যগুলি আপডেট করা কি আদৌ সম্ভব setState?

কিছুটা এইরকম:

this.state = {
   jasper: { name: 'jasper', age: 28 },
}

আমি চেষ্টা করেছি:

this.setState({jasper.name: 'someOtherName'});

এবং এই:

this.setState({jasper: {name: 'someothername'}})

প্রথম সিন্ট্যাক্স ত্রুটির ফলাফল এবং দ্বিতীয়টি কিছুই করে না। কোন ধারনা?


5
দ্বিতীয় কোডটি কাজ করত তবে আপনি নিজের ageসম্পত্তিটি হারিয়ে ফেলতেন jasper
জিওরজিম

উত্তর:


575

এই কাজ করার একাধিক উপায় আছে যেহেতু রাষ্ট্র আপডেট একটি হল ASYNC অপারেশন তাই রাষ্ট্র বস্তু আপডেট করার জন্য, আমরা ব্যবহার করতে হবে ফাংশন আপডেটার সঙ্গে setState

1- সহজতম:

প্রথমে একটি অনুলিপি তৈরি করুন jasperতারপরে এর পরিবর্তনগুলি করুন:

this.setState(prevState => {
  let jasper = Object.assign({}, prevState.jasper);  // creating copy of state variable jasper
  jasper.name = 'someothername';                     // update the name property, assign a new value                 
  return { jasper };                                 // return new object jasper object
})

ব্যবহারের পরিবর্তে Object.assignআমরা এটি এ জাতীয়ভাবে লিখতে পারি:

let jasper = { ...prevState.jasper };

2- স্প্রেড অপারেটর ব্যবহার করে :

this.setState(prevState => ({
    jasper: {                   // object that we want to update
        ...prevState.jasper,    // keep all other key-value pairs
        name: 'something'       // update the value of specific key
    }
}))

দ্রষ্টব্য: Object.assign এবং Spread Operatorকেবল অগভীর অনুলিপি তৈরি করে , তাই যদি আপনি নেস্টেড অবজেক্ট বা বস্তুর অ্যারে সংজ্ঞায়িত করেন তবে আপনার আলাদা পদ্ধতির প্রয়োজন।


নেস্টেড স্টেট অবজেক্ট আপডেট করা হচ্ছে:

ধরুন আপনি এই হিসাবে রাষ্ট্রকে সংজ্ঞায়িত করেছেন:

this.state = {
  food: {
    sandwich: {
      capsicum: true,
      crackers: true,
      mayonnaise: true
    },
    pizza: {
      jalapeno: true,
      extraCheese: false
    }
  }
}

পিজ্জা অবজেক্টের এক্সট্রাচিজ আপডেট করতে:

this.setState(prevState => ({
  food: {
    ...prevState.food,           // copy all other key-value pairs of food object
    pizza: {                     // specific object of food object
      ...prevState.food.pizza,   // copy all pizza key-value pairs
      extraCheese: true          // update value of specific key
    }
  }
}))

অবজেক্টের অ্যারে আপডেট করা হচ্ছে:

ধরে নেওয়া যাক আপনার একটি টুডো অ্যাপ্লিকেশন রয়েছে এবং আপনি এই ফর্মটিতে ডেটা পরিচালনা করছেন:

this.state = {
  todoItems: [
    {
      name: 'Learn React Basics',
      status: 'pending'
    }, {
      name: 'Check Codebase',
      status: 'pending'
    }
  ]
}

যে কোনও টুডো অবজেক্টের স্থিতি আপডেট করতে, অ্যারেতে একটি মানচিত্র চালান এবং প্রতিটি বস্তুর কিছু অনন্য মান পরীক্ষা condition=trueকরে দেখুন, নতুন মানটিকে আপডেট মান সহ অন্য কোনও বস্তুর সাথে ফিরে আসুন ।

let key = 2;
this.setState(prevState => ({

  todoItems: prevState.todoItems.map(
    el => el.key === key? { ...el, status: 'done' }: el
  )

}))

পরামর্শ: যদি বস্তুর কোনও স্বতন্ত্র মান না থাকে তবে অ্যারে সূচকটি ব্যবহার করুন।


আমি এখন যেভাবে চেষ্টা করছিলাম তা এখনও দ্বিতীয়ভাবে কাজ করে: এস
জনস্নো

7
@ জনস্নু আপনার মধ্যে দ্বিতীয় এটি jasperবস্তু থেকে অন্যান্য বৈশিষ্ট্যগুলি সরিয়ে দেবে , console.log(jasper)আপনি কি কেবল একটি কী দেখবেন name, বয়স সেখানে থাকবে না :)
মায়াঙ্ক শুক্লা

1
@JohnSnow, হ্যাঁ এই ভাবে সঠিক হলে jasperএকটি হল object, তাই না কিনা ভাল বা না হতে পারে অন্য ভালো সমাধান সম্ভব :)
মায়াঙ্ক শুক্লা

6
এখানে উল্লেখ করা ভাল যে Object.assignঅপারেটর গভীর অনুলিপি বৈশিষ্ট্যও নয়। এইভাবে আপনার লোডাশ deepCopyইত্যাদির মতো কাজের ক্ষেত্রগুলি ব্যবহার করা উচিত
অ্যালেক্স

1
কীভাবে let { jasper } = this.state?
ব্রায়ান লে

37

এটি দ্রুত এবং সর্বাধিক পঠনযোগ্য উপায়:

this.setState({...this.state.jasper, name: 'someothername'});

এমনকি যদি this.state.jasperইতিমধ্যে একটি নামের সম্পত্তি থাকে তবে নতুন নামটি name: 'someothername'ব্যবহার করা হবে।


38
এই সমাধানটির একটি বড় অসুবিধা রয়েছে: রাষ্ট্রীয় আপডেটগুলি অনুকূলিতকরণের জন্য প্রতিক্রিয়া একাধিক আপডেটের গোষ্ঠী হতে পারে। ফলাফল হিসাবে this.state.jasperঅগত্যা সর্বশেষতম রাষ্ট্রটি অন্তর্ভুক্ত থাকে না। সঙ্গে স্বরলিপি ব্যবহার ভাল prevState
পাপ করেছে

33

এখানে স্প্রেড অপারেটর এবং কিছু ES6 ব্যবহার করুন

this.setState({
    jasper: {
          ...this.state.jasper,
          name: 'something'
    }
})

এটি জাফার আপডেট করে তবে অন্যান্য বৈশিষ্ট্যগুলি রাজ্য থেকে সরানো হয়।
আইয়াক

11

আমি এই সমাধানটি ব্যবহার করেছি।

যদি আপনার মতো নেস্টেড রাজ্য থাকে:

this.state = {
  formInputs:{
    friendName:{
      value:'',
      isValid:false,
      errorMsg:''
    },
    friendEmail:{
      value:'',
      isValid:false,
      errorMsg:''
    }
  }
}

আপনি হ্যান্ডেল চেঞ্জ ফাংশনটি ঘোষণা করতে পারেন যা বর্তমান স্থিতিটি অনুলিপি করে এবং পরিবর্তিত মান সহ এটি পুনরায় নিয়োগ করে

handleChange(el) {
    let inputName = el.target.name;
    let inputValue = el.target.value;

    let statusCopy = Object.assign({}, this.state);
    statusCopy.formInputs[inputName].value = inputValue;

    this.setState(statusCopy);
  }

ইভেন্ট শ্রোতার সাথে এখানে এইচটিএমএল। রাষ্ট্রীয় বস্তুতে একই নাম ব্যবহার করা নিশ্চিত করুন (এই ক্ষেত্রে 'ফ্রেন্ডনাম')

<input type="text" onChange={this.handleChange} " name="friendName" />

এটি আমার পক্ষে কাজ করেছিল, কেবল তার পরিবর্তে আমাকে এটি ব্যবহার করতে হবে:statusCopy.formInputs[inputName] = inputValue;
মাইকিই

9

আমি জানি যে এখানে প্রচুর উত্তর রয়েছে তবে আমি অবাক হয়েছি তারা কেউই সেটস্টেটের বাইরে নতুন অবজেক্টের একটি অনুলিপি তৈরি করে না, এবং কেবলমাত্র সেটস্টেট ({newObject ject)} পরিষ্কার, সংক্ষিপ্ত এবং নির্ভরযোগ্য। সুতরাং এই ক্ষেত্রে:

const jasper = { ...this.state.jasper, name: 'someothername' }
this.setState(() => ({ jasper }))

বা একটি গতিশীল সম্পত্তি (ফর্ম জন্য খুব দরকারী) জন্য

const jasper = { ...this.state.jasper, [VarRepresentingPropertyName]: 'new value' }
this.setState(() => ({ jasper }))


7

এটি চেষ্টা করুন, এটি ভাল কাজ করা উচিত

this.setState(Object.assign(this.state.jasper,{name:'someOtherName'}));

4
আপনি সরাসরি রাষ্ট্রের বিষয়টিকে পরিবর্তন করছেন। এই পদ্ধতির ব্যবহার করতে, উত্স হিসাবে একটি নতুন অবজেক্ট যুক্ত করুন:Object.assign({}, this.state.jasper, {name:'someOtherName'})
আলবিজিয়া

3

প্রথম ক্ষেত্রেটি আসলে একটি বাক্য গঠন ত্রুটি।

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

this.state = {
  name: 'jasper',
  age: 28
}

এইভাবে, আপনি নামটি আপডেট করতে চান, আপনি কেবল কল করতে পারেন:

this.setState({
  name: 'Sean'
});

আপনি কি লক্ষ্য অর্জন করছেন তা কি তা অর্জন করবে?

বৃহত্তর, আরও জটিল ডেটা স্টোরের জন্য, আমি রেডাক্সের মতো কিছু ব্যবহার করব। তবে তা আরও অনেক উন্নত।

উপাদান উপাদান সহ সাধারণ নিয়মটি কেবলমাত্র উপাদানটির ইউআই অবস্থা পরিচালনা করার জন্য এটি ব্যবহার করা হয় (যেমন সক্রিয়, টাইমারস ইত্যাদি)

এই উল্লেখগুলি দেখুন:


1
আমি কেবল এটি ব্যবহার করেছি উদাহরণ হিসাবে, অবশ্যই অবশ্যই নেস্ট করা উচিত .. আমার সম্ভবত
রেডাক্স

2
হ্যাঁ, আমি আপাতত রেডাক্স থেকে দূরে থাকব। আপনি যখন মৌলিক বিষয়গুলি শিখছেন তখন আপনার ডেটা সহজ রাখার চেষ্টা করুন। এটি আপনাকে সেই ট্রিপগুলিকে এড়াতে সহায়তা করবে যা আপনাকে ট্রিপ করবে। 👍
এমসিসি ক্যামব্রিজ

2

অন্য বিকল্প: জেস্পার অবজেক্টের বাইরে আপনার ভেরিয়েবলটি সংজ্ঞায়িত করুন এবং তারপরে কেবল একটি ভেরিয়েবল কল করুন।

স্প্রেড অপারেটর: ES6

this.state = {  jasper: { name: 'jasper', age: 28 } } 

let foo = "something that needs to be saved into state" 

this.setState(prevState => ({
    jasper: {
        ...jasper.entity,
        foo
    }
})

2

সহজ এবং গতিশীল উপায়।

এটি কাজটি করবে, তবে আপনাকে সমস্ত আইডিকে পিতামাতার কাছে সেট করতে হবে যাতে পিতা-মাতা অবজেক্টের নাম ইড = "জাস্পার" হবে এবং বস্তুর জাস্পারের অভ্যন্তরে ইনপুট উপাদানটির নাম = সম্পত্তিটির নাম উল্লেখ করবে will ।

handleChangeObj = ({target: { id , name , value}}) => this.setState({ [id]: { ...this.state[id] , [name]: value } });

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

2

আপনি এটি দিয়ে চেষ্টা করতে পারেন : ( দ্রষ্টব্য : ইনপুট ট্যাগের নাম === অবজেক্টের ক্ষেত্র)

<input name="myField" type="text" 
      value={this.state.myObject.myField} 
     onChange={this.handleChangeInpForm}>
</input>

-----------------------------------------------------------
handleChangeInpForm = (e) => {
   let newObject = this.state.myObject;
   newObject[e.target.name] = e.target.value;
   this.setState({
     myObject: newObject 
   })
}

স্ট্যাক ওভারফ্লোতে আপনাকে স্বাগতম। যদিও এই কোডটি প্রশ্নের উত্তর দিতে পারে, কেন এবং / অথবা এই কোডটির প্রশ্নের উত্তর কীভাবে তার দীর্ঘমেয়াদী মানকে উন্নত করে তা সম্পর্কিত অতিরিক্ত প্রসঙ্গ সরবরাহ করে। কীভাবে উত্তর দিন
এললেটার

2

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

this.setState(
    produce(draft => {
       draft.jasper.name = 'someothername
    })
)

1

এছাড়াও, আলবার্তো পাইরাস সমাধান অনুসরণ করে, আপনি যদি সমস্ত "রাষ্ট্র" অবজেক্টটি অনুলিপি করতে চান না:

handleChange(el) {
    let inputName = el.target.name;
    let inputValue = el.target.value;

    let jasperCopy = Object.assign({}, this.state.jasper);
    jasperCopy[inputName].name = inputValue;

    this.setState({jasper: jasperCopy});
  }

1

আপনি এটি দিয়ে চেষ্টা করতে পারেন:

this.setState(prevState => {
   prevState = JSON.parse(JSON.stringify(this.state.jasper));
   prevState.name = 'someOtherName';
   return {jasper: prevState}
})

বা অন্য সম্পত্তি জন্য:

this.setState(prevState => {
   prevState = JSON.parse(JSON.stringify(this.state.jasper));
   prevState.age = 'someOtherAge';
   return {jasper: prevState}
})

অথবা আপনি হ্যান্ডেলচেজ ফাংশনটি ব্যবহার করতে পারেন:

handleChage(event) {
   const {name, value} = event.target;
    this.setState(prevState => {
       prevState = JSON.parse(JSON.stringify(this.state.jasper));
       prevState[name] = value;
       return {jasper: prevState}
    })
}

এবং এইচটিএমএল কোড:

<input 
   type={"text"} 
   name={"name"} 
   value={this.state.jasper.name} 
   onChange={this.handleChange}
/>
<br/>
<input 
   type={"text"} 
   name={"age"} 
   value={this.state.jasper.age} 
   onChange={this.handleChange}
/>

এটি JSON.stringify ছাড়াই কাজ করে .. this.setState (prevState => {prevState = this.state.docament; prevState.ValidDate = ইভেন্ট.target.value; prevState.ValidDate Format = day Format; return {ডকুমেন্ট: prevState}}); ..কখন নথির স্টেট টাইপ অবজেক্ট ..
ওলেগ বোরোডকো

1

Async এবং অপেক্ষা না করে এটি ব্যবহার করুন ...

funCall(){    
     this.setState({...this.state.jasper, name: 'someothername'});
}

আপনি যদি অ্যাসিঙ্ক এবং অ্যাওয়েটের সাহায্যে এটি ব্যবহার করেন ...

async funCall(){
      await this.setState({...this.state.jasper, name: 'someothername'});
}

0

এই সেটআপটি আমার পক্ষে কাজ করেছে:

let newState = this.state.jasper;
newState.name = 'someOtherName';

this.setState({newState: newState});

console.log(this.state.jasper.name); //someOtherName
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.