将所有单选按钮设置为false,然后在Redux reducer

时间:2018-01-28 11:29:01

标签: javascript ecmascript-6 redux

我似乎无法理解如何有效地将redux状态下的所有单选按钮设置为false,然后将原始动作创建器设置为true。

现在我努力尝试使用Object.assign复制状态对象,同时还提供了一种方法来更改item.type === 'radio'false的实际对象。

我认为某些代码可能接近真实的方式。

const state = {
  'some_id_1': {
    type: 'radio',
    id: 'some_id_1',
    checked: true
  }, 
  'some_id_2': {
    type: 'radio',
    id: 'some_id_2',
    checked: false
  }, 
  'some_id_3': {
    type: 'checkbox',
    id: 'some_id_3',
    checked: false
  }
};

const state = Object.assign({}, state, (item) => {
  if(item.type === 'radio') {
    console.log('reset='+item);
    item.checked = false;
  }
  return item;
});
return state;

但当然这不起作用,因为Object.assign不起作用。

当然我也可以遍历对象的键,即' radio_box_1_id',...并将item.type === 'radio'的任何内容设置为false,或者甚至将这些更改的值带出到一个单独的状态对象并使用另一个Object.assign参数替换它。但这些似乎是额外的处理时间,而不是我正在寻找的完美解决方案。

由于

编辑:我的目标是将我的州的项目设置为未检查状态,如果它们是收音机,但尽量不要更改其他项目。如果可能,我想有效地做到这一点。我之后可以将正确的电台设置为真。

1 个答案:

答案 0 :(得分:1)

虽然您没有指定state形状或reducer代码,但这是一项常见操作。

如果我理解正确,你会有一系列项目(对象),每个项目都有typeid。 如果typeradio,那么您将拥有checked属性。

如果这是正确的,您可以使用Array.prototype.map()方法并在检查操作有效负载内的id时有条件地返回一个新对象(使用object spread)。

这是一个小例子:

const state = [{
  type: 'radio',
  id: 1,
  checked: true
}, {
  type: 'radio',
  id: 2,
  checked: false
}, {
  type: 'text',
  id: 88,
  value: 'hi there'
}, {
  type: 'radio',
  id: 43,
  checked: false
}];
const action = {
  id: 2
};
console.log('before the change', state);
const nextState = state.map((item) => {
  if (item.type === 'radio') {
    return {
      ...item,
      checked: item.id === action.id
    }
  }
  return item; // not a radio, go on.

});
console.log('after the change', nextState);

<强>更新
作为更新的后续内容,现在我们知道了状态的形状,在处理对象而不是数组时,可以使用Object.keys迭代键并使用Array.prototype.reduce()创建新对象符合你的条件:

const state = {
  'some_id_1': {
    type: 'radio',
    id: 'some_id_1',
    checked: true
  },
  'some_id_2': {
    type: 'radio',
    id: 'some_id_2',
    checked: false
  },
  'some_id_3': {
    type: 'checkbox',
    id: 'some_id_3',
    checked: false
  }
};

const action = {
  id: 'some_id_2'
};
console.log('before the change', state);
const nextState = Object.keys(state).reduce((result,currentKey) => {
  const currentItem = state[currentKey];
  if (currentItem.type === 'radio') {
    result[currentKey] = {
      ...currentItem,
      checked: currentItem.id === action.id
    }
  } else{
  	result[currentKey] = currentItem // not a radio, go on.
  }
  return result; 

},{});
console.log('after the change', nextState);

修改
作为Ulysse BN评论的后续行动:

  

我不得不downvote:你修改过的答案并没有完全克隆状态。   如果在你的代码之后我运行状态['some_id_3']。foo ='bar',nextState   也将被修改,因为它们共享相同的对象引用。

这是误导性的,如果你没有改变一个对象,那么就没有必要重新创建它。这不是突变。

这是redux中的常见做法,您可以在Updating an Item in an Array

中详细了解相关信息