web-dev-qa-db-ja.com

ReactのsetStateを使ってオブジェクトを更新する

SETSTATEでオブジェクトのプロパティを更新するために、すべてのことは可能ですか?

何かのようなもの:

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

私が試してみました:

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

この:

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

最初は構文エラーで、2番目はちょうど何もしません。何か案は?

139
JohnSnow

これを行うための複数の方法があります。

1-最も簡単な1:

まず、その内の変更を行うjasperのコピーを作成します。

let jasper = Object.assign({}, this.state.jasper);    //creating copy of object
jasper.name = 'someothername';                        //updating value
this.setState({jasper});

Object.assignを使う代わりに、このように書くこともできます。

let jasper = {...this.state.jasper};

2-使用 拡散演算子

this.setState(prevState => ({
    jasper: {
        ...prevState.jasper,
        name: 'something'
    }
}))
299
Mayank Shukla

最速かつ最も読みやすい方法:

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

this.state.jasperにはすでにnameプロパティが含まれていますが、後者のname: 'someothername'を使用してください。

19
mannok

ここでスプレッド演算子とES6を使用する

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

私はこの解決策を使いました。

あなたがこのような入れ子になった状態があるならば:

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

現在のステータスをコピーして値を変更して再割り当てするhandleChange関数を宣言できます。

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);
  }

ここではイベントリスナーのHTMLです。状態オブジェクトに使用されているのと同じ名前(この場合は「friendName」)を必ず使用してください

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

これを試してください、それはうまく動作するはずです

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

最初のケースは確かに構文エラーです。

私はあなたのコンポーネントの残りを見ることができないので、あなたがここにあなたの状態でオブジェクトを入れ子にしている理由を見るのは難しいです。オブジェクトをコンポーネント状態でネストするのはお勧めできません。初期状態を次のように設定してみてください。

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

そのようにして、名前を更新したい場合は、単に呼び出すことができます。

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

それはあなたが目指していることを達成するでしょうか?

大規模で複雑なデータストアには、Reduxのようなものを使用します。しかし、それははるかに進んでいます。

コンポーネントの状態に関する一般的な規則は、コンポーネントのUI状態を管理するためだけにそれを使用することです(例えば、active、timerなど)。

これらの参考文献をチェックしてください。

3
mccambridge

また、すべての "state"オブジェクトをコピーしたくない場合は、Alberto Pirasの解決法に従ってください。

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});
  }
0
Marc LaQuay

シンプルでダイナミックな方法.

これは仕事をしますが、親がオブジェクトの名前を指すようにすべてのIDを親に設定する必要があります。id = "jasper"で、入力要素の名前を=オブジェクトjasperの内側に設定します。 。

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

これで試すことができます :(:入力タグの名前===オブジェクトのフィールド)

<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 
   })
}
0
Xuanduong Ngo

これは私のhandleInputChange関数です。あらゆる種類のオブジェクトに対して一般的な方法で機能します。しかし

evalの使用は強くお勧めできません

handleInputChange(event) {
  const target = event.target;

  const targetPropertyName = target.name.substr(target.name.indexOf('.'));
  const targetObjectName = target.name.substr(0, target.name.indexOf('.'));
  const value = target.value;

  var obj = this.state[targetObjectName];

  eval('obj' + targetPropertyName + '= value');

  this.setState({
    [targetObjectName]: obj
  });
}

そして私の入力フォーム

<input id="inputEmail" type="email" value={this.state.user.email} name="user.email" onChange={this.handleInputChange}/>

Eval関数に代わるアイデアはありますか?

0
juan

これで試すことができます:

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関数を使うこともできます。

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

とHTMLコード:

<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}
/>
0

もう1つの選択肢は、 Jasper オブジェクトから変数を定義してから、変数を呼び出すだけです。

拡散演算子: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
    }
})
0
Luis Martins

非同期を使用せずに待つこれを使用する...

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

あなたがAsync And Awaitで使っているならこれを使ってください /

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