0

I have some issue trying to update the state of my react functional componenet. I have set my componenet with my hook state like that.

function Tree(){


const [data,setData] = useState({
    id:1,
    label:'Root',
    children:[

    ],
    styles:{
        border:"1px solid green",
        padding:"10px 20px",
        position:"absolute",
        left:"45%",
        top:"20%",
  
      },
    content:{

    }
})




function addNode(parentId,nodeData){
    const newData = data;
    addChild(newData,parentId,nodeData)
    setData(newData);
}

function addChild(node,parentId,nodeData){
    if(parentId == node.id){
        
        node.children.push(nodeData);
        
     
         
    }else{
        //console.log("looking trough nodes")
        setNewState(node.children,parentId,nodeData)
    }
}

function deleteNode(nodeId){
    
}

console.log("rendering")

return (<>
    <Node children={data.children} styles={data.styles} addNode={addNode}></Node>
</>)
}

I am passing up the addNode method to the Node component through props and in the node component just called it in a click event. Im also using a recursive function to get a new state value, there's no problem to create a new value but I'd called out the state function and it doesnt rendering the component. I don't know what may be the reason that the state doesnt got updated. If some react exeprienced cant help me to resolve this problem, I'll be very greatfully with it. The addNode function takes an id and the value to add. The addChild method find the node recursively and pushed the value into itself children key. pd: Sorry for my english if is not good.

Manoj
  • 2,059
  • 3
  • 12
  • 24
  • Does this answer your question? [Why can't I directly modify a component's state, really?](https://stackoverflow.com/questions/37755997/why-cant-i-directly-modify-a-components-state-really) – Emile Bergeron Oct 02 '20 at 15:08

2 Answers2

1

It's best practice to never mutate React state, which you are doing with node.children.push as node is a reference to the state data.

I would recommend that addChild should return a new object altogether that setData would be called with. Or I don't see why addChild couldn't call setData itself. But either way data should be cloned, and the clone is what should be mutated and passed to setData.

Also, with the functional nature of React, it is also best practice to not have functions mutate their parameters as addChild does.

Zeke Hernandez
  • 1,226
  • 11
  • 14
  • Oh I see now, that really helped me a lot. That works perfectly, I solved it just clonning the data object with the Object.assign function. Thank you so much – george delaselva Oct 02 '20 at 15:18
  • glad to help, also, a lot of folks will use the spread operator to clone an objects like in Halil's answer: `const newObject = [...oldObject]` as shorthand for `Object.assign`. Note that both of these functions only do a shallow clone, not a deep clone. Also, just speaking from experience, I find it much easier to manage having many different calls to `useState` that each keep track of one thing, like 'label', 'id', 'children' etc. Instead of one call with a big state object. – Zeke Hernandez Oct 02 '20 at 16:45
0
function addNode(parentId,nodeData){
   const newData = {...data};
   addChild(newData,parentId,nodeData)
   setData(newData);
}
Halil
  • 121
  • 7