Redux: 質問:レデューサー内の状態での内部オブジェクトの変異

作成日 2016年04月15日  ·  3コメント  ·  ソース: reduxjs/redux

これは有効なreduxレデューサーですか?

function reducer(state={ byId: {}, ids: [] }, action) {
  switch (action.type) {
    case 'ADD':
      state = { ...state }
      state.byId[action.id] = action.value
      state.ids.push(action.id)
      return state

    default:
      return state
  }
}

状態全体が最初にシャロークローンされるため、新しいオブジェクトが返されますが、内部オブジェクトは同じままで変更されます。

または、次のようなことをする必要がありますか?

function reducer(state={ byId: {}, ids: [] }, action) {
  switch (action.type) {
    case 'ADD':
      return {
        ...state,
        byId: {
          ...state.byId,
          [action.id]: action.value
        },
        ids: [ ...state.ids, action.id ]
      }

    default:
      return state
  }
}

最初のアプローチで見られる副作用は、DevToolsLogMonitorにあります。

  • 以前の状態でサブノード(例: byId )を展開すると、以前は別の状態であった場合でも、最新のノードと同じ値が表示されます
  • タイムトラベルが機能していない

LogMonitorの単なるバグですか、それとも2番目のアプローチが正しいですか? ミューテーションの前にstate = _.cloneDeep(state)を追加すると、実際には正常に機能し、LogMonitorが同じオブジェクト、つまり同じ値を再利用することを証明します。

アプリの残りの部分は正常に動作しますが、 @connect edビューは正しく更新されます。

最も参考になるコメント

後者の例はあなたがする必要があることです。 明らかに、あなたが物事を入れ子にしているなら、それは幾分冗長になる可能性があります。 あなたのためにそれを抽象化しようとするいくつかのユーティリティライブラリがあります、そして私はそれらのいくつかを私のReduxライブラリリストの不変データページにリストしています。

また、レデューサー構成はこれに役立ちます。

function byId(state = {}, action) {
  switch (action.type) {
    case 'ADD':
      return {
        ...state,
        [action.id]: action.value
      }
    default:
      return state
  }
}

function ids(state = [], action) {
  switch (action.type) {
    case 'ADD':
      return [ ...state, action.id ]
    default:
      return state
  }
}

const reducer = combineReducers({
  byId,
  ids
})

全てのコメント3件

いいえ、その最初の例は状態を完全に変化させることです。 最初の浅いコピーは新しいオブジェクトを作成しますが、新しいオブジェクトは元のオブジェクトと同じbyIdおよびids参照を指します。 したがって、 byId[action.id] = action.valueids.push(action.id)を実行すると、元のアイテムが変更されます。

後者の例はあなたがする必要があることです。 明らかに、あなたが物事を入れ子にしているなら、それは幾分冗長になる可能性があります。 あなたのためにそれを抽象化しようとするいくつかのユーティリティライブラリがあります、そして私はそれらのいくつかを私のReduxライブラリリストの不変データページにリストしています。

Redux FAQには、状態を不変に正しく更新することをカバーする質問もあります: http: //redux.js.org/docs/FAQ.html#react-not-rerendering。

後者の例はあなたがする必要があることです。 明らかに、あなたが物事を入れ子にしているなら、それは幾分冗長になる可能性があります。 あなたのためにそれを抽象化しようとするいくつかのユーティリティライブラリがあります、そして私はそれらのいくつかを私のReduxライブラリリストの不変データページにリストしています。

また、レデューサー構成はこれに役立ちます。

function byId(state = {}, action) {
  switch (action.type) {
    case 'ADD':
      return {
        ...state,
        [action.id]: action.value
      }
    default:
      return state
  }
}

function ids(state = [], action) {
  switch (action.type) {
    case 'ADD':
      return [ ...state, action.id ]
    default:
      return state
  }
}

const reducer = combineReducers({
  byId,
  ids
})

@ gaearon @ markeriksonありがとう。 動的なインデックス付きリストを(IDで)管理する高次リデューサーを作成することになりました。

コード: https ://gist.github.com/elado/95484b754f31fcd6846c7e75de4aafe4

このページは役に立ちましたか?
0 / 5 - 0 評価