2015-10-01 16 views
6

から属性を削除することができます私はそれは状態だ上で設定されたプロパティを持っていた反応の成分を持っている場合はどのように私はReactjsコンポーネントの状態オブジェクト

onClick() { 
    this.setState({ foo: 'bar' }); 
} 

Object.keys(this.state)からここ"foo"を削除することが可能ですか?

replaceStateメソッドは、試してみると明らかな方法のように見えますが、それ以降は償却されています。

答えて

7

あなたはとても

var Hello = React.createClass({ 
    getInitialState: function() { 
     return { 
      foo: 10, 
      bar: 10 
     } 
    }, 

    handleClick: function() { 
     this.setState({ foo: undefined }); 
    }, 

    render: function() { 
     return (
      <div> 
       <div onClick={ this.handleClick.bind(this) }>Remove foo</div> 
       <div>Foo { this.state.foo }</div> 
       <div>Bar { this.state.bar }</div> 
      </div> 
     ); 
    } 
}); 

Example

また、あなたがdelete

delete this.state.foo; 
this.setState(this.state); 

を使用することができますが、このソリューションは、直接this.stateを操作するので、これは危険であるように、undefinedfooを設定することができます

更新

以前のソリューションあなたは完全に可能な解決策の一つがそうのように、片方の親keysetStateすることができ、stateからキーを削除する必要がある場合だけfookeyスキルから値を削除すると、stateに存在します

var Hello = React.createClass({ 
 
    getInitialState: function() { 
 
    return { 
 
     data: { 
 
     foo: 10, 
 
     bar: 10 
 
     } 
 
    } 
 
    }, 
 
    \t 
 
    handleClick: function() { 
 
    const state = { 
 
     data: _.omit(this.state.data, 'foo') 
 
    }; 
 
    
 
    this.setState(state,() => { 
 
     console.log(this.state); 
 
    }); 
 
    }, 
 
     
 
    render: function() { 
 
    return (
 
     <div> 
 
     <div onClick={ this.handleClick }>Remove foo</div> 
 
     <div>Foo { this.state.data.foo }</div> 
 
     <div>Bar { this.state.data.bar }</div> 
 
     </div> 
 
    ); 
 
    } 
 
}); 
 

 
ReactDOM.render(<Hello />, document.getElementById('container'))
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="container"></div>

2

以前の解決策 - 反パターンです。これはthis.stateを変更するためです。違います!

使用この(古い方法):

let newState = Object.assign({}, this.state) // Copy state 
newState.foo = null // modyfy copyed object, not original state 
// newState.foo = undefined // works too 
// delete newState.foo // Wrong, do not do this 
this.setState(newState) // set new state 

または使用ES6砂糖:

this.setState({...o, a:undefined}) 

かなり甘い、あなたがいないのですか?古いで))

は、構文(オリジナルではなく、ES6)、これは、ストア内の不要なキーを削除this.replaceStateを、持っているが反応するが、今それはあなたのアプリケーションの状態の簡易コピーを作成するObject.assignを使用することができますdeprecated

+0

これらのソリューションの両方とも間違っています。第1の理由は、 'Object.assign()'は[深いクローンを行いません](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign #Deep_Clone)ので、より複雑なアプリケーションを意識せずに状態を直接変更する可能性があります。 2つ目の問題は両方のソリューションで発生し、@ alexander-tの答えと同じです。 Object.keys()からキーを削除しているわけではありません。あなたはその価値を変えているだけです。 – Vince

+0

はい、私はObject.keysについて知っていますが、私の応答は問題を解決します。そして、あなたは私に2回downvoteとして悪い気性を持っています。 – MiF

+0

このトピックは私にとって感情的な意義はなく、誰も2度投票することはできません。私はあなたの答えを一度投票しました。なぜなら、それは質問によって引き起こされた問題を解決しないからです。しかし、どのようにしてこの問題が解決するのかよく分かりません。状態オブジェクトのプロパティを反復してリストやテーブルを作成する場合、そのうちの1つの値を 'null' /' undefined'に設定すると、少なくとも空のリスト項目やテーブル行が生成されます。コードが子オブジェクトのプロパティを使用するように記述されている場合、値を 'null' /' undefined'に設定すると、トラブルシューティングが困難なエラーが発生します。 – Vince

1

です適切な深さで削除し、コピーから要素を削除します。次に、setStateを使用して、変更されたコピーをアプリケーションの状態にマージします。

これは完璧な解決策ではありません。このようにオブジェクト全体をコピーすると、パフォーマンス/メモリの問題が発生する可能性があります。 Object.assignのシャローコピーは、メモリ/パフォーマンスの問題を緩和するのに役立ちますが、新しいオブジェクトのどの部分がコピーであり、どの部分がアプリケーション状態のデータへの参照であるかを意識する必要もあります。

以下の例では、ingredientsの配列を変更すると、実際にアプリケーションの状態が直接変更されます。

望ましくない要素の値をnullまたはundefinedに設定しても、それが削除されません。

const Component = React.Component; 
 

 
class App extends Component { 
 
    constructor(props) { 
 
    super(props); 
 
    this.state = { 
 
     "recipes": { 
 
     "1": { 
 
      "id": 1, 
 
      "name": "Pumpkin Pie", 
 
      "ingredients": [ 
 
      "Pumpkin Puree", 
 
      "Sweetened Condensed Milk", 
 
      "Eggs", 
 
      "Pumpkin Pie Spice", 
 
      "Pie Crust" 
 
      ] 
 
     }, 
 
     "2": { 
 
      "id": 2, 
 
      "name": "Spaghetti", 
 
      "ingredients": [ 
 
      "Noodles", 
 
      "Tomato Sauce", 
 
      "(Optional) Meatballs" 
 
      ] 
 
     }, 
 
     "3": { 
 
      "id": 3, 
 
      "name": "Onion Pie", 
 
      "ingredients": [ 
 
      "Onion", 
 
      "Pie Crust", 
 
      "Chicken Soup Stock" 
 
      ] 
 
     }, 
 
     "4": { 
 
      "id": 4, 
 
      "name": "Chicken Noodle Soup", 
 
      "ingredients": [ 
 
      "Chicken", 
 
      "Noodles", 
 
      "Chicken Stock" 
 
      ] 
 
     } 
 
     }, 
 
     "activeRecipe": "4", 
 
     "warningAction": { 
 
     "name": "Delete Chicken Noodle Soup", 
 
     "description": "delete the recipe for Chicken Noodle Soup" 
 
     } 
 
    }; 
 
    
 
    this.renderRecipes = this.renderRecipes.bind(this); 
 
    this.deleteRecipe = this.deleteRecipe.bind(this); 
 
    } 
 
    
 
    deleteRecipe(e) { 
 
    const recipes = Object.assign({}, this.state.recipes); 
 
    const id = e.currentTarget.dataset.id; 
 
    delete recipes[id]; 
 
    this.setState({ recipes }); 
 
    } 
 
    
 
    renderRecipes() { 
 
    const recipes = []; 
 
    for (const id in this.state.recipes) { 
 
     recipes.push((
 
     <tr> 
 
      <td> 
 
      <button type="button" data-id={id} onClick={this.deleteRecipe} 
 
      >&times;</button> 
 
      </td> 
 
      <td>{this.state.recipes[id].name}</td> 
 
     </tr> 
 
    )); 
 
    } 
 
    return recipes; 
 
    } 
 
       
 
    render() { 
 
    return (
 
     <table> 
 
     {this.renderRecipes()} 
 
     </table> 
 
    ); 
 
    } 
 
} 
 

 
ReactDOM.render(<App />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<main id="app"></main>

2

次のコードは、直接this.stateを変異させずにthis.stateからfooを削除します:

const {foo, ...state} = this.state; 
this.setState({state}); 

あなたが仕事に、このためstage 3 presetが必要になります。

+0

それは理解するのに少し読んだ。私は破壊を認めているが、私はそれをあまり使わなかった。 'Object.assign'と同じように、スプレッド演算子[1レベル深く進む](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Spread_operator#Copy_an_array)。ですから、Object.assignを使った私のソリューションと事実上同じですが、動作させるにはBabelの追加設定が必要です。 – Vince

+1

浅いクローニングはOKで、実際にはエンコードされているため高速です。あなたが不変でなければならないものの周りのルールに従う限り、それは問題ありません。 React docsが 'react-addons-update'の代わりに推奨する' immutability-helper'ライブラリも同じことをしています。 –

+0

多くの人がステージnのプリセットを使用しています。ステージ3はかなり保守的です。これは3までのすべての段階で動作します。 –

0

ReactCompositeComponent.jsのGitHubのリアクションソースには、_processPendingStateというメソッドがあります。これは、component.setStateの呼び出しから状態をマージする究極の方法です。

`` ` _processPendingState:function(props、context){ var inst = this._instance; var queue = this._pendingStateQueue; var replace = this._pendingReplaceState; this._pendingReplaceState = false; this._pendingStateQueue = null;

if (!queue) { 
    return inst.state; 
} 

if (replace && queue.length === 1) { 
    return queue[0]; 
} 

var nextState = replace ? queue[0] : inst.state; 
var dontMutate = true; 
for (var i = replace ? 1 : 0; i < queue.length; i++) { 
    var partial = queue[i]; 
    let partialState = typeof partial === 'function' 
    ? partial.call(inst, nextState, props, context) 
    : partial; 
    if (partialState) { 
    if (dontMutate) { 
     dontMutate = false; 
     nextState = Object.assign({}, nextState, partialState); 
    } else { 
     Object.assign(nextState, partialState); 
    } 
    } 
} 

`` `マージを実装し、実際のラインを見ることができるコードで

nextState = Object.assign({}, nextState, partialState); 

どこにもこの機能では、それは本当に行動を意図していない意味deleteまたは類似の呼び出しは、ありません。また、setStateは常にマージであるため、statを完全にコピーし、プロパティを削除し、setStateを呼び出すことはできません。したがって、deletedプロパティは無視されます。

また、setStateはすぐには機能しませんが、バッチが変更されるため、状態オブジェクト全体を複製して1つのプロパティの変更のみを試みると、以前のsetStateの呼び出しを消去する可能性があります。 Reactの文書によれば、

リアクションでは、複数のsetState()呼び出しを1つのアップデートにまとめてパフォーマンスを向上させることができます。

this.propsとthis.stateが非同期に更新される可能性があるため、次の状態を計算するためにその値に依存するべきではありません。

実際にはもっと情報を追加することができます。

this.setState({ xSet: true, x: 'foo' }); 
this.setState({ xSet: false, x: undefined }); 

これは許可され、醜いですが、それはあなたがundefinedに設定された値、およびすべてで設定されていない値を区別するために必要な情報の余分な部分を提供します。加えて、Reactの内部、トランザクション、状態変更のバッチ処理、その他の恐怖にはうってつけです。2番目の推測を試みるよりも複雑さを増やす方が良いでしょう。トランザクション調整のような恐怖、replaceStateのような非難される機能の管理などに繋がります。

0

削除が関数内にあり、変数にするには、これを試してみてください:

スティーブの答えとほぼ同じですが、関数内にあります。

関連する問題