How to delete a linked node?
Describe the bug craft json: { "ROOT": { "type": { "resolvedName": "PageContainer" }, "isCanvas": true, "props": { }, "displayName": "APP", "hidden": false, "nodes": [ "dseJuw_N09" ], "linkedNodes": {} }, "dseJuw_N09": { "type": { "resolvedName": "TabsWrapper" }, "isCanvas": false, "props": { }, "displayName": "Tabs", "custom": {}, "parent": "ROOT", "hidden": false, "nodes": [], "linkedNodes": { "simple-tabpanel-0": "4UMnl2CvbA", "simple-tabpanel-1": "7nsOGA7ixG", "simple-tabpanel-2": "OQA1r8DNvq" } }, "4UMnl2CvbA": { "type": { "resolvedName": "Container" }, "isCanvas": true, "props": { }, "displayName": "Container", "custom": {}, "parent": "dseJuw_N09", "hidden": false, "nodes": [], "linkedNodes": {} }, "7nsOGA7ixG": { "type": { "resolvedName": "Container" }, "isCanvas": true, "props": { }, "displayName": "Container", "custom": {}, "parent": "dseJuw_N09", "hidden": true, "nodes": [], "linkedNodes": {} }, "OQA1r8DNvq": { "type": { "resolvedName": "Container" }, "isCanvas": true, "props": { }, "displayName": "Container", "custom": {}, "parent": "dseJuw_N09", "hidden": true, "nodes": [], "linkedNodes": {} } }
To Reproduce Steps to reproduce the behavior:
const { actions } = useEditor() actions.delete("OQA1r8DNvq")
Error: Invariant failed: Attempting to delete a top-level Node
Expected behavior
Screenshots If applicable, add screenshots to help explain your problem.
Additional context Add any other context about the problem here.
Your environment
| Software | Version(s) |
|---|---|
| craft.js | |
| React | |
| TypeScript | |
| Browser | |
| npm/Yarn | |
| Operating System |
Same issue.
@prevwong is deleting linked nodes possible?
Yes, same issue here.
I'm having a similar issue. The error thrown is:
react-dom.development.js:20724 Uncaught
Error: Invariant failed: Attempting to delete a top-level Node
at invariant (tiny-invariant.js:16:11)
at eval (index.js:43:38192)
at Array.forEach (<anonymous>)
at Object.delete (index.js:43:38100)
at eval (index.js:57:8173)
at e.produce (immer.esm.mjs:25:16108)
at e.produceWithPatches (immer.esm.mjs:25:16689)
at eval (index.js:57:7864)
at eval (index.js:57:8966)
at e.reduce.e.<computed> (index.js:57:9462)
at onClick (PanelControllerSettingsPanel.tsx:72:19)
at HTMLUnknownElement.callCallback (react-dom.development.js:20565:14)
at Object.invokeGuardedCallbackImpl (react-dom.development.js:20614:16)
at invokeGuardedCallback (react-dom.development.js:20689:29)
at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:20703:25)
at executeDispatch (react-dom.development.js:32128:3)
at processDispatchQueueItemsInOrder (react-dom.development.js:32160:7)
at processDispatchQueue (react-dom.development.js:32173:5)
at dispatchEventsForPlugins (react-dom.development.js:32184:3)
at eval (react-dom.development.js:32374:12)
at batchedUpdates$1 (react-dom.development.js:24953:12)
at batchedUpdates (react-dom.development.js:28844:12)
at dispatchEventForPluginEventSystem (react-dom.development.js:32373:3)
at dispatchEvent (react-dom.development.js:30141:5)
at dispatchDiscreteEvent (react-dom.development.js:30112:5)
```
Same issue.
PSA the only way I got this to work properly was processing the editor state in my backend every time a change is published, deleting the node there, and then have Craft re-render with the updated state
thanks @jorgegonzalez!
fwiw this is my workaround:
const deleteNode = (nodeId: string) =>{
if(!query.node(nodeId).isLinkedNode()){
actions.delete(nodeId);
}else{
const ancestors = query.node(nodeId).ancestors();
if (ancestors.length > 0) {
deleteNode(ancestors[0]);
}
}
}
@ck6u4dj0 your function deletes linkedNode's parent, which is not what is generally needed. I have a ColumnsBlock component. If the user decreases the number of columns I need to delete the linked nodes that are the extra columns. I do not want (and cannot) delete the ColumnsBlock itself.
I find it frustrating that when my ColumnsBlock renders, if it does not render the extra column, that component remains in the editor's state anyway, even though it was never rendered.
@prevwong, this is a serious issue. Is there a way to delete linked nodes?
edit: I may have solved this similar to @jorgegonzalez, but in the front end. I call const state = JSON.parse(query.seriealize()), manipulate the state, then re-render with action.deserialize(state). It works, but it's slow and scrolls to the top of the page. It's extra frustrating that async functions cannot be waited on.