更新几个属性

Update several properties

ramda 中,如何一次更新多个属性?我能得到的最接近的是使用 R.evolve()evolve 要我使用转换函数修改 属性。我想直接做。但是,R.assoc() 一次只能修改一个 属性,我必须使用字符串指定 属性。

我现在就是这样用 evolve:

const STATE_INITIAL = {
    isDisabled: true,
    isLoading: false
};

R.evolve({
    isDisabled: R.not, 
    isLoading: () => true // I don't want to set a value using a function
    }, state)

在 JS 中,我会使用 object-spread 运算符,然后我会收到一个新对象:

{ ...state, isDisabled: !state.isDisabled, isLoading: true}

一种选择是使用镜头:

const isDisabled = R.lensProp('isDisabled');
const isLoading = R.lensProp('isLoading');

//    toggle :: State -> State
const toggle = R.pipe(
  R.over(isDisabled, R.not),
  R.set(isLoading, true)
);

toggle({isDisabled: true, isLoading: false});
// => {isDisabled: false, isLoading: true}

参见 R.lensProp, R.over, and R.set

Ramda 试图让事情变得简单,所以不太可能有一种好的技术可以让你对一个 属性 使用一个函数,对另一个使用一个值,除非像 David Chambers 建议的那样通过管道传递它们。他的,版本,也可以这样写:

const toggle = R.pipe(
  R.over(R.lensProp('isDisabled'), R.not),
  R.set(R.lensProp('isLoading'), true)
)

肯定比

更冗长
const toggle = state => {
  ...state,
  isDisabled: !state.isDisabled, 
  isLoading: true    
}

不过好像还不错。但是,如果您对对这两个属性使用函数的反对不是太强烈,那么原始版本的变体 evolve 非常简单:

const toggle = R.evolve({
  isDisabled: R.not, 
  isLoading: R.T
})

R.T 只是 shorthand 对于 R.always(true)