I have an array of objects. Each object looks like this:
{ "key": "pQSa6jgmsbFnQgJ1memDJ", "type": "div", "props": { "id": "pQSa6jgmsbFnQgJ1memDJ", "style": { "height": "100px", "backgroundColor": "#de4141" }, "className": "" }, "selected": true, "childNodes": [{ "key": "pQSa6jgmsbFnQgJ1memDJ", "type": "div", "props": { "id": "VrrQ1rMUOF6IOOKAZomor", "style": { "height": "100px", "backgroundColor": "#de4141" }, "className": "" }, "selected": false, "childNodes": [] }] }
The problem is that each object can have childNodes
, and those childs can have also more childs…
The property that I want to change is selected
. This property defines wether the object is selected or not and therefore display a different className in the DOM. I have a function to deselect all (change all the object’s selected property to false) that looks like this, where content
is a React state
, the array containing this objects:
function () { const $ = _.cloneDeep(content); const z = $.map((c) => { let y = c; if (y?.childNodes && y.childNodes.length > 0) { y.childNodes = y.childNodes.map((h) => { let x = h; x.selected = false; return x; }); } y.selected = false; return y; }); setContent(z); setActive(null); }
But this will only change the first childNodes. What if these childNodes have also more childNodes? I would need to do a map, again, for those childNodes manually. Is there a way to do this (e.g using lodash
,which I’m alreay using for cloneDeep()
)?
Advertisement
Answer
You could use a recursive approach to set the required property values. We’d create a function like ‘setPropertyDeep’, pass along the property value required.
This will update the object tree to any depth.
const input = { "key": "pQSa6jgmsbFnQgJ1memDJ", "type": "div", "props": { "id": "pQSa6jgmsbFnQgJ1memDJ", "style": { "height": "100px", "backgroundColor": "#de4141" }, "className": "" }, "selected": true, "childNodes": [{ "key": "pQSa6jgmsbFnQgJ1memDJ", "type": "div", "props": { "id": "VrrQ1rMUOF6IOOKAZomor", "style": { "height": "100px", "backgroundColor": "#de4141" }, "className": "" }, "selected": false, "childNodes": [] }] } function updatePropertyDeep(obj, property, value) { for(let k in obj) { if (k === property) { obj[property] = value; } else if (obj[k] && typeof(obj[k]) === 'object') { updatePropertyDeep(obj[k], property, value); } } return obj; } console.log('Setting true:', updatePropertyDeep(input, 'selected', true)) console.log('Setting false:', updatePropertyDeep(input, 'selected', false))
.as-console-wrapper { max-height: 100% !important; }