2017-12-02 9 views
2

私は減速機内の状態を更新しようとしています。オブジェクトやネストされたオブジェクトを変更するべきではないことがわかりますmapオブジェクトの配列やオブジェクトスプレッドの場合しかし、私は本当に深くネストされた値を変更することはできないようです。オブジェクトと配列を変更していない場合でも、減速機のネストされたオブジェクトを変更することはできません

私は状態を変えることができませんが、実際にコードがどのように見えているのか、特に1つのプロパティを変更するだけのループの数が嫌です。私はこれを行うためのより良い、読みやすく、より良い方法があるように感じる。

これは状態です:

const items = [{ 
    name: 'item 1', 
    id: 'item1', 
    tags: [{ 
    id: 'tag1', 
    name: 'tag 1' 
    }, { 
    id: 'tag2', 
    name: 'tag 2' 
    }] 
}, { 
    name: 'item 2', 
    id: 'item2', 
    tags: [{ 
    id: 'tag1', 
    name: 'tag 1' 
    }, { 
    id: 'tag4', 
    name: 'tag 4' 
    }] 
}]; 

これは私が派遣だアクションです:

const action = { 
    type: 'CHANGE_TAG_NAME', 
    payload: { 
    itemId: 'item2', 
    tagId: 'tag4', 
    newTagName: 'tag 44444' 
    } 
}; 

これは減速です:

​​

答えて

1

あなたのレデューサーはうまくいくはずです。nextStateをあなたのケースブロックに返すことを忘れました。現在のアイテムのidがあるとして、それを返しますが、ペイロードに持ってitemIdと異なっている場合、アイテムを超える
マップ:

は以下の反復のために、私はこのパターンを示唆しています。
アイテムのIDが同じ場合は、新しいオブジェクトを返し、タグをマップして、アイテムと同じ条件を実行します。
タグのIDがペイロード内のtagIdと同じでない場合はそのまま返し、同じ場合は新しいオブジェクトを返します。ここで

が実行されている例である:より読みやすいコードについては

const items = [{ 
 
    name: 'item 1', 
 
    id: 'item1', 
 
    tags: [{ 
 
    id: 'tag1', 
 
    name: 'tag 1' 
 
    }, { 
 
    id: 'tag2', 
 
    name: 'tag 2' 
 
    }] 
 
}, { 
 
    name: 'item 2', 
 
    id: 'item2', 
 
    tags: [{ 
 
    id: 'tag1', 
 
    name: 'tag 1' 
 
    }, { 
 
    id: 'tag4', 
 
    name: 'tag 4' 
 
    }] 
 
}]; 
 

 
const action = { 
 
    type: 'CHANGE_TAG_NAME', 
 
    payload: { 
 
    itemId: 'item2', 
 
    tagId: 'tag4', 
 
    newTagName: 'tag 44444' 
 
    } 
 
}; 
 

 
const itemsReducer = (state = [], action) => { 
 
    switch (action.type) { 
 
    case 'CHANGE_TAG_NAME': 
 
     { 
 
     const { 
 
      payload: { 
 
      itemId, 
 
      tagId, 
 
      newTagName 
 
      } 
 
     } = action; 
 
     const nextState = state.map(item => { 
 
      if (item.id !== itemId) return item; 
 
      return { 
 
      ...item, 
 
      tags: item.tags.map(tag => { 
 
       if (tag.id !== tagId) return tag; 
 
       return { 
 
       ...tag, 
 
       name: newTagName 
 
       } 
 
      }) 
 
      } 
 
     }); 
 
     return nextState; 
 
     } 
 
    default: 
 
     return state; 
 
    } 
 
}; 
 

 
console.log(itemsReducer(items, action));

、私はより多くのレデューサーを使用することをお勧めします。
itemsReducer、
itemReducer、
tagsReducer、
tagReducer:
私が使用したルールの親指は、エンティティごと減速を作成することです。

このようにして、各レデューサーは自分のデータを管理します。ここで

が実行されている例です。

const items = [{ 
 
    name: 'item 1', 
 
    id: 'item1', 
 
    tags: [{ 
 
    id: 'tag1', 
 
    name: 'tag 1' 
 
    }, { 
 
    id: 'tag2', 
 
    name: 'tag 2' 
 
    }] 
 
}, { 
 
    name: 'item 2', 
 
    id: 'item2', 
 
    tags: [{ 
 
    id: 'tag1', 
 
    name: 'tag 1' 
 
    }, { 
 
    id: 'tag4', 
 
    name: 'tag 4' 
 
    }] 
 
}]; 
 

 
const action = { 
 
    type: 'CHANGE_TAG_NAME', 
 
    payload: { 
 
    itemId: 'item2', 
 
    tagId: 'tag4', 
 
    newTagName: 'tag 44444' 
 
    } 
 
}; 
 

 
const tagReducer = (state = {}, action) => { 
 
    switch (action.type) { 
 
    case 'CHANGE_TAG_NAME': 
 
     { 
 
     const { 
 
      payload: { 
 
      newTagName 
 
      } 
 
     } = action; 
 
     const nextState = { 
 
      ...state, 
 
      name: newTagName 
 
     } 
 
     return nextState; 
 
     } 
 
    default: 
 
     return state; 
 
    } 
 
} 
 

 
const tagsReducer = (state = [], action) => { 
 
    switch (action.type) { 
 
    case 'CHANGE_TAG_NAME': 
 
     { 
 
     const { 
 
      payload: { 
 
      tagId 
 
      } 
 
     } = action; 
 
     const nextState = state.map(tag => { 
 
      if (tag.id !== tagId) return tag; 
 
      return tagReducer(tag, action); 
 
     }); 
 
     return nextState; 
 
     } 
 
    default: 
 
     return state; 
 
    } 
 
} 
 

 

 
const itemReducer = (state = {}, action) => { 
 
    switch (action.type) { 
 
    case 'CHANGE_TAG_NAME': 
 
     { 
 
     const nextState = { 
 
      ...state, 
 
      tags: tagsReducer(state.tags, action) 
 
     } 
 
     return nextState; 
 
     } 
 
    default: 
 
     return state; 
 
    } 
 
} 
 

 
const itemsReducer = (state = [], action) => { 
 
    switch (action.type) { 
 
    case 'CHANGE_TAG_NAME': 
 
     { 
 
     const { 
 
      payload: { 
 
      itemId 
 
      } 
 
     } = action; 
 
     const nextState = state.map(item => { 
 
      if (item.id !== itemId) return item; 
 
      return itemReducer(item, action) 
 
     }); 
 
     return nextState; 
 
     } 
 
    default: 
 
     return state; 
 
    } 
 
}; 
 

 
console.log(itemsReducer(items, action));

このパターンはちょうどそれらを使用し、多くの場合、減速組成と呼ばれ、あなたのルート減速でそれらのすべてを含める必要はありませんあなたの他のレデューサーのための国の関連部分を計算する外部の純粋な関数として。

+1

これはいいパターンです。私はもう少しそれを勉強する必要があります –

+0

あなたは歓迎です:) –

2

あなたがキーワードを忘れてしまったreturn

//..... 
    const nextState = [ 
     ...state.slice(0, itemIndex), 
     nextItem, 
     ...state.slice(itemIndex + 1) 
    ]; 
    // HERE RETURN 
    return newState; 
    } 
default: 
    return state; 
+0

よろしくお願い致します。 –

関連する問題