//helper to get prop from object
const get = (object, path, defaultValue) => {
const recur = (object, path) => {
if (object === undefined) {
return defaultValue;
}
if (path.length === 0) {
return object;
}
return recur(object[path[0]], path.slice(1));
};
return recur(object, path);
};
//helper to set nested prop in object
const set = (
state,
statePath,
modifier
) => {
const recur = (result, path) => {
const key = path[0];
if (path.length === 0) {
return modifier(get(state, statePath));
}
return Array.isArray(result)
? result.map((item, index) =>
index === Number(key)
? recur(item, path.slice(1))
: item
)
: {
...result,
[key]: recur(result[key], path.slice(1)),
};
};
const newState = recur(state, statePath);
return get(state, statePath) === get(newState, statePath)
? state
: newState;
};
let state = {
items: {
'item-1': {
id: 'item-1',
title: 'To do',
task: ['task-1', 'task-2', 'task-3', 'task-4'],
},
'item-2': {
id: 'item-2',
title: 'In progress',
task: [],
},
},
};
console.log(
set(
state,
['items','item-1','task'],
(tasks)=>tasks.concat('new task')
)
);