2017-12-02 63 views
2

我试图更新机内部的状态改变嵌套的对象,所以我用map,我知道我不应该发生变异的对象或嵌套对象为数组或对象传播对象。但似乎我无法真正改变深度嵌套的价值。不是可以在减速,即使不变异的对象和数组

旁边的事实,我不能改变的状态,我真的不喜欢代码的样子,尤其是环路我需要做的数量,只是改变一个属性。我觉得这样做有更好,更可读和更高效的方式。

这是国家:

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。

这样每个reducer将负责自己的数据。

这里是一个正在运行的例子:

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));

这种模式通常被称为减速器组成,你不必包括在你的根减速所有这些,只是使用它们作为外部纯函数来计算你的其他reducer的相关部分。

+1

这是一个很好的模式谢谢。我应该多学习一下 –

+0

不客气:) –

2

你忘了关键字return

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

是啊我傻谢谢 –

相关问题