首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >扩展算子与immutable.js的比较

扩展算子与immutable.js的比较
EN

Stack Overflow用户
提问于 2018-11-22 21:01:24
回答 1查看 5.7K关注 0票数 11

当使用时,immutable.js几乎已经成为一个行业标准。我的问题是,当我们使用扩展运算符时,我们不是在不断地修改我们的redux状态吗?例如,

代码语言:javascript
复制
const reducer = (state=initialState, action) => {
    switch(action.type){
        case actionType.SOME_ACTION:
            return {
                ...state,
                someState: state.someState.filter(etc=>etc)
            }
    }

难道我用redux不可变的方式来设置状态吗?使用immutable.js operator使对象不可变的好处是什么?

如果有人问了这个问题,我很抱歉,但我找不到满意的答案。我理解不可变对象的好处,但不理解使用immutable.js库而不是点运算符的重要性。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-22 21:05:01

简短回答

是!ES6扩展操作符可以完全用作immutable.js的替代品,但是有一个重要的警告,您必须在任何时候都保持对情况的了解。

很长的答案

您和您的其他开发人员将百分之百地负责维护不变性,而不是让immutable.js来照顾您。这里详细介绍了如何使用ES6‘like运算符’以及它的各种函数(如filtermap )来管理不可变的状态。

下面将探索如何以不可变和可变的方式将值移除并添加到数组或对象。我在每个示例中注销了initialStatenewState,以演示我们是否已经变异了initialState。这很重要,因为如果initialStatenewState完全相同,Redux就不会指示UI重新呈现。

注意:如果您尝试了以下任何一种不同的解决方案, Immutable.js都会使应用程序崩溃。

从数组中删除元素

不变方式

代码语言:javascript
复制
const initialState = {
  members: ['Pete', 'Paul', 'George', 'John']
}
const reducer = (state, action) => {
  switch(action.type){
case 'REMOVE_MEMBER':
  return {
    ...state,
    members: state.members.filter(
      member => member !== action.member
    )
  }
  }
}
const newState = reducer(
  initialState,
  {type: 'REMOVE_MEMBER', member: 'Pete'}
);

console.log('initialState', initialState);
console.log('newState', newState);

突变方式

代码语言:javascript
复制
const initialState = {
  members: ['Pete', 'Paul', 'George', 'John']
}
const reducer = (state, action) => {
  switch(action.type){
case 'REMOVE_MEMBER':
  state.members.forEach((member, i) => {
    if (member === action.member) {
      state.members.splice(i, 1)
    }
  })
  return {
    ...state,
    members: state.members
  }
  }
}
const newState = reducer(
  initialState,
  {type: 'REMOVE_MEMBER', member: 'Pete'}
);

console.log('initialState', initialState);
console.log('newState', newState);

将元素添加到数组

不变方式

代码语言:javascript
复制
const initialState = {
  members: ['Paul', 'George', 'John']
}
const reducer = (state, action) => {
  switch(action.type){
case 'ADD_MEMBER':
  return {
    ...state,
    members: [...state.members, action.member]
  }
  }
}
const newState = reducer(
  initialState,
  {type: 'ADD_MEMBER', member: 'Ringo'}
);

console.log('initialState', initialState);
console.log('newState', newState);

突变方式

代码语言:javascript
复制
const initialState = {
  members: ['Paul', 'George', 'John']
}
const reducer = (state, action) => {
  switch(action.type){
case 'ADD_MEMBER':
  state.members.push(action.member);
  return {
    ...state,
    members: state.members
  }
  }
}
const newState = reducer(
  initialState,
  {type: 'ADD_MEMBER', member: 'Ringo'}
);

console.log('initialState', initialState);
console.log('newState', newState);

更新阵列

不变方式

代码语言:javascript
复制
const initialState = {
  members: ['Paul', 'Pete', 'George', 'John']
}
const reducer = (state, action) => {
  switch(action.type){
case 'UPDATE_MEMBER':
  return {
    ...state,
    members: state.members.map(member => member === action.member ? action.replacement : member)
  }
  }
}
const newState = reducer(
  initialState,
  {type: 'UPDATE_MEMBER', member: 'Pete', replacement: 'Ringo'}
);

console.log('initialState', initialState);
console.log('newState', newState);

突变方式

代码语言:javascript
复制
const initialState = {
  members: ['Paul', 'Pete', 'George', 'John']
}
const reducer = (state, action) => {
  switch(action.type){
case 'UPDATE_MEMBER':
  state.members.forEach((member, i) => {
    if (member === action.member) {
      state.members[i] = action.replacement;
    }
  })
  return {
    ...state,
    members: state.members
  }
  }
}
const newState = reducer(
  initialState,
  {type: 'UPDATE_MEMBER', member: 'Pete', replacement: 'Ringo'}
);

console.log('initialState', initialState);
console.log('newState', newState);

合并阵列

不变方式

代码语言:javascript
复制
const initialState = {
  members: ['Paul', 'Ringo']
}
const reducer = (state, action) => {
  switch(action.type){
case 'MERGE_MEMBERS':
  return {
    ...state,
    members: [...state.members, ...action.members]
  }
  }
}
const newState = reducer(
  initialState,
  {type: 'MERGE_MEMBERS', members: ['George', 'John']}
);

console.log('initialState', initialState);
console.log('newState', newState);

突变方式

代码语言:javascript
复制
const initialState = {
  members: ['Paul', 'Ringo']
}
const reducer = (state, action) => {
  switch(action.type){
case 'MERGE_MEMBERS':
  action.members.forEach(member => state.members.push(member))
  return {
    ...state,
    members: state.members
  }
  }
}
const newState = reducer(
  initialState,
  {type: 'MERGE_MEMBERS', members: ['George', 'John']}
);

console.log('initialState', initialState);
console.log('newState', newState);

对经验丰富的开发人员来说,上面的数组变异示例似乎是一个明显的不良实践,但对于新开发人员来说,这是一个很容易的陷阱。我们希望任何变异的代码片段都会被捕获到代码评审中,但情况并不总是如此。让我们来谈谈对象,这些对象在自己处理不可变性时更麻烦。

从对象中移除

不变方式

代码语言:javascript
复制
const initialState = {
  members: {
paul: {
  name: 'Paul',
  instrument: 'Guitar'
},
stuart: {
  name: 'Stuart',
  instrument: 'Bass'
}
  }
}
const reducer = (state, action) => {
  switch(action.type){
case 'REMOVE_MEMBER':
  let { [action.member]: _, ...members } = state.members
  return {
    ...state,
    members
  }
  }
}
const newState = reducer(
  initialState,
  {type: 'REMOVE_MEMBER', member: 'stuart'}
);

console.log('initialState', initialState);
console.log('newState', newState);

突变方式

代码语言:javascript
复制
const initialState = {
  members: {
paul: {
  name: 'Paul',
  instrument: 'Guitar'
},
stuart: {
  name: 'Stuart',
  instrument: 'Bass'
}
  }
}
const reducer = (state, action) => {
  switch(action.type){
case 'REMOVE_MEMBER':
  delete state.members[action.member]
  return {
    ...state,
    members: state.members
  }
  }
}
const newState = reducer(
  initialState,
  {type: 'REMOVE_MEMBER', member: 'stuart'}
);

console.log('initialState', initialState);
console.log('newState', newState);

更新对象

不变方式

代码语言:javascript
复制
const initialState = {
  members: {
paul: {
  name: 'Paul',
  instrument: 'Guitar'
},
ringo: {
  name: 'George',
  instrument: 'Guitar'
}
  }
}
const reducer = (state, action) => {
  switch(action.type){
case 'CHANGE_INSTRUMENT':
  return {
    ...state,
    members: {
      ...state.members,
      [action.key]: {
        ...state.members[action.member],
        instrument: action.instrument
      }
    }
  }
  }
}
const newState = reducer(
  initialState,
  {type: 'CHANGE_INSTRUMENT', member: 'paul', instrument: 'Bass'}
);

console.log('initialState', initialState);
console.log('newState', newState);

突变方式

代码语言:javascript
复制
const initialState = {
  members: {
paul: {
  name: 'Paul',
  instrument: 'Guitar'
},
ringo: {
  name: 'George',
  instrument: 'Guitar'
}
  }
}
const reducer = (state, action) => {
  switch(action.type){
case 'CHANGE_INSTRUMENT':
  state.members[action.member].instrument = action.instrument
  return {
    ...state,
    members: state.members
  }
  }
}
const newState = reducer(
  initialState,
  {type: 'CHANGE_INSTRUMENT', member: 'paul', instrument: 'Bass'}
);

console.log('initialState', initialState);
console.log('newState', newState);

如果你成功了,恭喜你!我知道这是一个冗长的帖子,但我觉得重要的是展示所有变异的方式,,您需要防止自己没有Immutable.js。除了防止您编写糟糕的代码之外,使用Immutable.js的一个巨大优势是助手方法,如mergeDeepupdateIn

Immutable.JS

mergeDeep

代码语言:javascript
复制
const initialState = Immutable.fromJS({
  members: {
    paul: {
      name: 'Paul',
      instrument: 'Guitar'
    },
    ringo: {
      name: 'George',
      instrument: 'Guitar'
    }
  }
})
const reducer = (state, action) => {
  switch (action.type) {
    case 'ADD_MEMBERS':
      return state.mergeDeep({members: action.members})
  }
}
const newState = reducer(
  initialState,
  {
    type: 'ADD_MEMBERS',
    members: {
      george: { name: 'George', instrument: 'Guitar' },
      john: { name: 'John', instrument: 'Guitar' }
    }
  }
);

console.log('initialState', initialState);
console.log('newState', newState);
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.min.js"></script>

updateIn

代码语言:javascript
复制
const initialState = Immutable.fromJS({
  members: {
    paul: {
      name: 'Paul',
      instrument: 'Guitar'
    },
    ringo: {
      name: 'George',
      instrument: 'Guitar'
    }
  }
})
const reducer = (state, action) => {
  switch (action.type) {
    case 'CHANGE_INSTRUMENT':
      return state.updateIn(['members', action.member, 'instrument'], instrument => action.instrument)
  }
}
const newState = reducer(
  initialState,
  {type: 'CHANGE_INSTRUMENT', member: 'paul', instrument: 'Bass'}
);

console.log('initialState', initialState);
console.log('newState', newState);
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.min.js"></script>

票数 24
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53437937

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档