2017-02-06 10 views
3

私のコードは動作しますが、私はベストプラクティスの質問があります。私は状態のオブジェクトの配列を持っており、ユーザーのやり取りは一度に1つのオブジェクトの値を変更します。限り、私は知っている限り、私は直接国を変更するはずはない、私は常にsetStateを使用する必要があります。もし私がそれを避けたいなら、私は反復によって配列を深くクローンし、クローンを変更します。次に、状態をクローンに設定します。私の意見では、後で変更する状態を変更することを避けることは、単にパフォーマンスを低下させることです。React - setStateを使用せずに状態を変更する:回避する必要がありますか?

詳細バージョン: this.state.dataはオブジェクトの配列です。それはフォーラム内のトピックのリストを表し、FavoriteボタンはclickCollect()を呼び出してトグルします。 私は状態の配列を持っているので、1つのアイテムのis_collectedプロパティを変更するときは、作業する配列のコピーを作成し、新しい値に変更した後に状態に設定する必要があります。

var data = this.state.data.slice(0); 
data[index].is_collected = !data[index].is_collected; 
this.setState({data: data}); 

var data = this.state.data:これはアレイ及びプッシュ(へのポインタをコピーする)、等シフト()は、直接、状態を変化させるであろう。 datathis.state.dataの両方が影響を受けます。

var data = this.state.data.slice(0):これは浅いクローンを作成しますが、pushとshiftは状態を変更しませんが、私のクローンではまだステートの配列の要素へのポインタを持っています。だから私がdata[0].is_collectedを変更した場合、this.state.data[0].is_collectedも同様に変更されます。これは私がsetState()に電話する前に起こります。

は、通常、私は実行する必要があります。

var data = []; 
for (var i in this.state.data) { 
    data.push(this.state.data[i]); 
} 
その後

それは本当だとき、それは虚偽または虚偽だとき、私はこれをtrueに設定し、インデックスの値を変更します。

data[index].is_collected = !data[index].is_collected; 

状態を変更:

this.setState({data: data}); 

私の配列が比較的大きいか、非常に大きいです考えてみて、私はこの繰り返しが私のAPPのパフォーマンスが低下しますね。私はそれが何らかの理由で正しい方法であることが分かっていれば、私はその費用を支払うでしょう。ただし、この関数(clickCollect)では、常に新しい値を状態に設定していますが、変更をやめるのを止める偽のAPI応答を待っているわけではありません。すべての場合、新しい値が状態に入ります。実際には、setStateは、UIを再レンダリングするためだけに呼び出します。したがって、質問は次のとおりです。

  1. この場合、ディープクローンを作成する必要がありますか? (for var i in ...
  2. 私の配列にオブジェクトが含まれている場合、浅いクローン(.slice(0))を作成するのは意味がありますか?変更はアレイ内部のオブジェクト上で行われているので、コピー(data = this.state.data)のように、浅いクローンは自分の状態を変更します。

私のコードは単純化されており、簡単にするためにAPI呼び出しが省略されています。

これは初心者の質問です。全く異なるアプローチも歓迎します。あなたのアプリは非常に壊れやすい作りと基本的に全体を無視して、状態が直接(単方向とされている)のリアクトデータ・フローの主な原則を破るミュートまたは他のQへのリンク& A.

import React from 'react'; 

var ForumList = React.createClass({ 
    render: function() { 
     return <div className="section-inner"> 
     {this.state.data.map(this.eachBox)} 
     </div> 
    }, 
    eachBox: function(box, i) { 
    return <div key={i} className="box-door"> 
     <div className={"favorite " + (box.is_collected ? "on" : "off")} onTouchStart={this.clickCollect.bind(null, i)}> 
      {box.id} 
     </div> 
    </div> 
    }, 
    getInitialState: function() { 
    return {data: [ 
     { 
     id: 47, 
     is_collected: false 
     }, 
     { 
     id: 23, 
     is_collected: false 
     }, 
     { 
     id: 5, 
     is_collected: true 
     } 
    ]}; 
    }, 
    clickCollect: function(index) { 
    var data = this.state.data.slice(0); 
    data[index].is_collected = !data[index].is_collected; 
    this.setState({data: data}); 
    } 
}); 

module.exports = ForumList; 
+0

ありがとうございました。私は4人すべてが異なる視点から問題にいくつかの光を当てているので、実際にはそれらのうちの1つを「受け入れる」ことはできません。しかし、@CodinCatは彼の答えをそう明確に述べるために受け入れを受けます。VJAI、Kelvin De Moyaとdegrに特別なおかげです。 –

答えて

0

個人的に私はいつもルールに従っているわけではありませんが、本当にあなたが何をしようとしているのか分かっていれば、それは問題ではないと思います。この場合

var data = this.state.data.slice(0); 
data[index].is_collected = !data[index].is_collected; 
this.setState({data: data}); 

、状態を変異し、このように再びsetStateを呼び出すと

this.state.data[index].is_collected = !this.state.data[index].is_collected; 
this.setState({data: this.state.data}); 

結構です、あなたの状態を変異避けるべきである理由は、あなたが this.state.dataへの参照を持っている場合ということです、そして setStateを呼び出しますこのことについてあなたが本当に懸念している場合、

const myData = this.state.data 
myData[0] = 'foo' 
this.setState({ data: myData }) 
// do something... 
// ... 
const someNewData = someFunc() 
this.setState({ data: someNewData }) 

myData[1] = 'bar' // myData is still referencing to the old state 
this.setState({ data: myData }) // you lose everything of `someNewData` 

だけのために行く:複数回、あなたはあなたのデータを失う可能性があり

0

コンポーネントのライフサイクル。

したがって、setState({})を使用せずにコンポーネントの状態を変更することは実際にはありませんが、本当にReactを利用したい場合は、それを避けなければならないでしょう。そうしないと、ライブラリのコア機能

0

私は右のあなたの質問を理解している場合は、オブジェクトの配列を持っていると、配列の変化で、単一のオブジェクトのプロパティは、

  1. 配列の深いクローンを作成し、SETSTATE
  2. に渡します
  3. シャローコピーを作成し、私はちょうどreduxsample todo appと私でチェック

をSETSTATEに渡しますオブジェクトの単一のプロパティのnの場合は、配列全体ではなくその単一のオブジェクトの新しいコピーを作成するために変更されます。 reduxについて読んで、可能であればアプリの状態を管理することをお勧めします。

0

ベストプラクティスに従うには、プロパティを変更するときに、すべてのアレイをシャローコピーする必要があります。不変のライブラリの実装を見てください。

しかし、「shouldCompomenentUpdate」実装がある場合は、私の経験から、そして私の意見では、setStateメソッドを呼び出す必要があります。あなたの浅いコピーはもっと多くのリソースを消費し、仮想ドミノチェックに反応すると思うなら、これを行うことができます:

this.state.data[0].property = !this.state.data[0].property; 
this.forceUpdate(); 
関連する問題