Reputation: 21595
In ramda
how can I update several properties at once? The closest I could get was using R.evolve()
. evolve
wants me to modify a property using a transformation function. I would like to do it directly. However, R.assoc()
lets me modify only one property at a time and I have to specify the property using a string.
This is how I do it now with 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)
In JS I would the object-spread
operator and I would receive a new object:
{ ...state, isDisabled: !state.isDisabled, isLoading: true}
Upvotes: 3
Views: 439
Reputation: 50807
Ramda tries to keep things simple, so there's not likely a good technique that would allow you to use a function for one property and a value for another, except by piping them through as David Chambers suggests. His, version, which can also be written like this:
const toggle = R.pipe(
R.over(R.lensProp('isDisabled'), R.not),
R.set(R.lensProp('isLoading'), true)
)
is certainly somewhat more verbose than
const toggle = state => {
...state,
isDisabled: !state.isDisabled,
isLoading: true
}
But it doesn't seem that bad. However, if your objection to using functions for both properties is not too strong, there's a variant of your original version with evolve
that's pretty simple:
const toggle = R.evolve({
isDisabled: R.not,
isLoading: R.T
})
R.T
is simply shorthand for R.always(true)
Upvotes: 1
Reputation: 24856
One option is to use lenses:
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}
See R.lensProp
, R.over
, and R.set
.
Upvotes: 2