2017-01-01 13 views
3

コンテキスト変更値

私はテキスト要素の動的なセットでフォームをレンダリングしています。 normalizr principlesを使用して状態を正規化しました。そのため、elementIdsの配列と、elementIdsによって参照される要素プロパティを含むオブジェクトがあります(下のコードサンプルの初期状態を参照)。 2つのレンダリングされた要素が編集可能にするために

目的

私の目的は単純です。私は正常にonChangeコールバックを使用して私の店にアクションCHANGE_ELEMENT_VALUEを送り、action.id(変更された要素のidを参照する)とaction.value(新しい値)はレデューサーで利用可能です(下記のコードを参照)。

問題

は私の問題は、私は状態はデベロッパーツールReduxの拡張機能を使用して変更すること見ることができるにもかかわらず、私が入力したときにテキストフィールドが変更されていないということです。私の理解は、変化は状態が深いので、反応は状態の変化を認識していないということです。私は新しい状態のオブジェクトをうまく作成していないので、おそらく古いインスタンスを何とか参照しています。

減速コードの下

は、新しい状態オブジェクトを強制的に私の不手際の試みです。私は、コンポーネントが再レンダリングされていないので、動作していないと仮定しています。それはまた非常に控えめなようです。

let initialState = { 
    isLoading: false, 
    data: { 
     elementIds: ['name', 'email'], 
     elements: { 
      'name': {'id': 'name', 'value':'ben'}, 
      'email': {'id':'email', 'value':'[email protected]'}, 
     }, 
    }, 
    error: false 
} 

function formReducer(state = initialState, action = null) { 
    switch(action.type) { 
     case types.CHANGE_ELEMENT_VALUE: 
      let newData = Object.assign(state.data) 
      newData.elements[action.id].value = action.value 
      return {...state, data: newData} 

     default: 
      return state; 
    } 
} 

export default formReducer; 
+0

私が気づいた最初の考えは、あなたが 'Object.assign'を悪用しているということです。テストすると、 'newData === state.data'ということが分かります。これは、最初の引数がターゲットであるためです。一般的に言えば、オブジェクトを深くクローンするこの "問題"があります(構造が動的であれば醜いものになります)ので、以下の答えが役に立つかもしれません。私は個人的にhttps://www.npmjs.com/package/icepick –

答えて

2

あなたはimmutability-helper npm packageを利用し、自分の価値観を更新することができ、あなたの減速に

import update from 'immutability-helper'; 

let initialState = { 
    isLoading: false, 
    data: { 
     elementIds: ['name', 'email'], 
     elements: { 
      'name': {'id': 'name', 'value':'ben'}, 
      'email': {'id':'email', 'value':'[email protected]'}, 
     }, 
    }, 
    error: false 
} 

function formReducer(state = initialState, action = null) { 
    switch(action.type) { 
     case types.CHANGE_ELEMENT_VALUE: 
      return update(state, { 
       data : { 
        elements: { 
         [action.id]: { 
           value: { 
            $set: 'new value' 
           } 
          } 
        } 
       } 
      }) 

     default: 
      return state; 
    } 
} 

export default formReducer; 

update()提供このパターンの周りの単純な構文的な砂糖は、 このコードを書くのが簡単になります。構文は少し曖昧ですが、 はMongoDBのクエリ言語に触発されていますが、 の冗長性はありません。静的に解析可能であり、突然変異バージョンよりもはるかにタイピングされていません( )。

+0

ありがとう@ shubham-khatri。あなたや他の誰かが、これがlinkiwiが上記で示唆したディープ・エクステンション・オプションよりも優れているかどうかについて意見を持っていますか? – xanld

1

Object.assignは1レベルしか動作しません。すなわち、オブジェクトツリー全体を再帰的にクローン化しない。したがって、トップレベルのオブジェクトはクローンされますが、レデューサーはクローンオブジェクトの深い値を変更するため、再レンダリングを開始しません。

私はdeep-extendパッケージに見て、次のように自分の状態を更新推薦:

import extend from 'deep-extend'; 

... 

return extend(state, { 
    elements: { 
    [key]: value 
    } 
}); 
+0

を使います。これは便利です。パフォーマンスに関する罰則、私の国家構造に関する懸念、そしてキーストロークごとにツリー全体を再現しなければならないという事実は、ただ一つの値で一つの値を変更することに関係していますか? – xanld