question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Clone element work only after serialize and deserialize

See original GitHub issue

Describe the bug A little bit of context, in https://github.com/prevwong/craft.js/issues/144 the first solution for cloning elements causes linked cloned nodes to change props to the original ones, https://github.com/prevwong/craft.js/issues/144#issuecomment-788700366 seems to have the same problem, but actually the nodes ids are changed and if we deserialize a serialized state editor inside a setTimeout function it works. To Reproduce Steps to reproduce the behavior:

  1. Go to https://codesandbox.io/s/epic-colden-giwsw
  2. Select a button, on the settings panel under delete click clone
  3. Try to changes some props to the cloned element
  4. You can see that props are changed to the original one.
  5. Now uncomment line 87 on settings panel https://codesandbox.io/s/epic-colden-giwsw?file=/components/SettingsPanel.js:2258-2268
  6. Now the clone function works

Expected behavior Cloning an element and run actions.addNodeTree should load the correct data.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

9reactions
nicoshcommented, Mar 10, 2021

Here is a working function for cloning elements (sandbox) :

  const getCloneTree = useCallback((idToClone) => {
   const tree = query.node(idToClone).toNodeTree();
   const newNodes = {};

   const changeNodeId = (node, newParentId) => {
     const newNodeId = shortid();
     const childNodes = node.data.nodes.map((childId) => changeNodeId(tree.nodes[childId], newNodeId));
     const linkedNodes = Object.keys(node.data.linkedNodes).reduce(
       (accum, id) => {
         const newNodeId = changeNodeId(
           tree.nodes[node.data.linkedNodes[id]],
           newNodeId,
         );
         return {
           ...accum,
           [id]: newNodeId,
         };
       },
       {},
     );

     let tmpNode = {
       ...node,
       id: newNodeId,
       data: {
         ...node.data,
         parent: newParentId || node.data.parent,
         nodes: childNodes,
         linkedNodes,
       },
     };
     let freshnode = query.parseFreshNode(tmpNode).toNode()
     newNodes[newNodeId] = freshnode
     return newNodeId;
   };

   const rootNodeId = changeNodeId(tree.nodes[tree.rootNodeId]);
   return {
     rootNodeId,
     nodes: newNodes,
   };
 }, []);

The problem was this piece of code that i guess did not update the internal state :

      newNodes[newNodeId] = {
        ...node,
        id: newNodeId,
        data: {
          ...node.data,
          parent: newParentId || node.data.parent,
          nodes: childNodes,
          linkedNodes
        }
      };

While using query.parseFreshNode seems to work fine :

      let tmpNode = {
        ...node,
        id: newNodeId,
        data: {
          ...node.data,
          parent: newParentId || node.data.parent,
          nodes: childNodes,
          linkedNodes,
        },
      };
      let freshnode = query.parseFreshNode(tmpNode).toNode()
1reaction
PurviJhacommented, Mar 7, 2021

This is awsome solution to our problem but there is a bug i face .After deserializing the json, drag and drop stopped working It has unexpected behaviour .while checking the official example(basic one) when click on lode state it deserialize the json and drag and drop stopped working while switch on and off enable button drag and drop started working .May be this is not the solution but its a quick fix

Read more comments on GitHub >

github_iconTop Results From Across the Web

c# - Cloning objects without Serialization - Stack Overflow
Json serialization and deserialization should work, it doesn't require the classes to have serialize annotation.
Read more >
Serialize and Deserialize a Binary Tree - GeeksforGeeks
Serialization is to store the tree in a file so that it can be later restored. The structure of the tree must be...
Read more >
How to serialize and deserialize JSON using C# - .NET
To write JSON to a string or to a file, call the JsonSerializer.Serialize method. The following example creates JSON as a string: C#...
Read more >
Marker Interface In Java: Serializable And Cloneable
It also covers Serialization Deserialization and Cloning in Java with ... After we are done with the marker interface we will discuss two ......
Read more >
Simple 2.7.1 - Simple XML Serialization
As can be seen the deserialization process is just as simple. The persister is given the class representing the serialized object and the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found