Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possibility for onNodesChange to return metadata about which node(s) were modified #177

Open
timc1 opened this issue Feb 5, 2021 · 1 comment

Comments

@timc1
Copy link
Contributor

timc1 commented Feb 5, 2021

Is your feature request related to a problem? Please describe.

Please correct me if there is a current solution!

It seems like we currently have to send the entire editor state on every save – ideally, we can store each block separately, and on onNodesChange, only make the request needed for the specific node(s) that were updated

Describe the solution you'd like

onNodesChange containing some metadata regarding which nodes have updated – an object representing the nodeId and the action taken would be ideal?

Top of mind:

{
  node: "123",
  action: "deleted" | "moved" | "added" 
}
@ankri
Copy link
Collaborator

ankri commented Feb 8, 2021

I can't think of a nice way to do it. But I wrote a hacky proof of concept on how to accomplish it. The nicer way would be to extend the current functionality.

You could create a Watcher Component which will receive a custom onNodesChange callback.

function Watcher({
  onNodesChange
}: {
  onNodesChange: (timeline: any) => void;
}) {
  const { store, nodes } = useEditor((state) => {
    return { nodes: state.nodes };
  });

  React.useEffect(() => {
    onNodesChange(store.history.timeline);
  }, [nodes]);

  return null;
}

Problem: The effect fires like crazy.

CodeSandbox

Edit: Clicked on submit too early...

This will provide you with access to the whole timeline. From there on you can access the last Patch that has been added to the timeline. But you would have to do the serialization and stuff manually.


I've updated my code:

function Watcher({
  onNodesChange
}: {
  onNodesChange: (lastAddedNode: Node) => void;
}) {
  const { store, nodes, query } = useEditor((state, query) => {
    // using state.nodes would result in too calls of the useEffect
    // getSerializedNodes is more stable 
    return { nodes:  query.getSerializedNodes()};
  });


  React.useEffect(() => {
    // only run when there is a change
    if(store.history.timeline.length > 0) {
      // this only works for adding nodes to root...
      // we only need the patches
      const [rootPatch, addedNodePatch] = store.history.timeline[store.history.timeline.length - 1].patches;
      const lastAddedNode = query.node(addedNodePatch.value.id)
      
      onNodesChange(lastAddedNode.get());
    }
  }, [nodes, onNodesChange, store.history.timeline, query]);

  return null;
}

With these changes the useEffect will not run as frequently and onNodesChange will be called with the last node that was added to root.

Attention This hack will only work with nodes directly added to root.

Updated CodeSandbox

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants