Change Value Properties in Object with Ramda Lense

2019-05-18 03:25发布

问题:

I would like to know how can I change object properties with Ramda Lenses.

Currently, I have a deep state :

buckets[
    blocks[
        messages[
            replies [
                {id: 0, text: 'text 0', value: 'simple value 0'},
                {id: 1, text: 'text 1', value: 'simple value 1'},
                {id: 2, text: 'text 2', value: 'simple value 2'},
                ...
            ]
        ]
    ]
]

I have a basic payload. I would like to get the property and the value, and set the old value by the new value in my state, for example with this payload :

{text: 'new_text'} or {value: 'new_value'}

In my reducer I have this :

case SEQUENCES.UPDATE_REPLY_ON_BLOCK :
// payload => {text: 'new_text'}, or {value: 'new_value'}, or anyway...

let key = Object.keys(payload)[0];
let value = payload[key];

return R.over(
  R.lensPath(["buckets", 0, "blocks", 0, "messages", 0, "replies", 0, key]),
  R.set(value),
  state
);

I tried with Merge :

return R.over(
    R.lensPath(["buckets", 0, "blocks", 0, "messages", 0, "replies", 0),
    R.merge(payload),
    state,
);

But same result : the state is not modified and I have no error.

Maybe SOLVED with mergeDeepLeft :

//payload => {value: 'new_value'}

return R.over(
    R.lensPath(["buckets", 0, "blocks", 0, "messages", 0, "replies", 0),
    R.mergeDeepLeft(payload),
    state,
);

回答1:

You're close. The problem is that R.set and R.over are used for two different tasks. You don't need over here. Instead your outer function should be set and the second parameter the value you want to set the lens to:

const payload = {text: 'new_text'}
const key = Object.keys(payload)[0];
const value = payload[key];

const state = {buckets: [{blocks: [{messages: [{replies: [{id: 0, text: 'text 0', value: 'simple value 0'}, {id: 1, text: 'text 1', value: 'simple value 1'}, {id: 2, text: 'text 2', value: 'simple value 2'}]}]}]}]}

console.log(
    R.set(
        R.lensPath(['buckets', 0, 'blocks', 0, 'messages', 0, 'replies', 0, key]),
        value,
        state,
    )
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

You use over when you want to adjust it based on the value that's already there, passing a function from old value to new value as the second parameter. For instance, R.over(myLens, R.toUpper, obj):

const payload = {text: 'new_text'}
const key = Object.keys(payload)[0];
const value = payload[key];

const state = {buckets: [{blocks: [{messages: [{replies: [{id: 0, text: 'text 0', value: 'simple value 0'}, {id: 1, text: 'text 1', value: 'simple value 1'}, {id: 2, text: 'text 2', value: 'simple value 2'}]}]}]}]}

console.log(
    R.over(
        R.lensPath(['buckets', 0, 'blocks', 0, 'messages', 0, 'replies', 0, key]),
        R.toUpper,
        state,
    )
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>