1

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())?

3
  • You need to recursively update it for every childNodes Commented Jul 29, 2022 at 12:21
  • What do you mean with that? Commented Jul 29, 2022 at 12:23
  • Write a function that changes the selected property of an object. If there's a childNodes property with childs in it call that function for every child/object. Rinse and repeat... Commented Jul 29, 2022 at 12:24

2 Answers 2

2

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; }

Sign up to request clarification or add additional context in comments.

Comments

1

use recursion

function updateChild(child){
  if (!child || !Array.isArray(child)) {
    return
  }
  return child.map(el => {
    return {
      ...el,
      selected: false,
      childNodes: updateChild(el.childNodes)
    }
  })
}

function main() {
      return updateChild(content);
      //setContent(z);
      //setActive(null);
      
}

const content = [
  {
    "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": []
    }]
}
]

document.getElementById('result').innerHTML = JSON.stringify(main(), null, 2)
<pre id="result"></pre>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.