xyflow: Library breaks when trying to create an Edge from a Handle that is generated programmatically

Hi guys! First of all, thanks for the amazing library that React Flow is.

I’ve a Custom Node where I need to programmatically generate the Source Handles based on a list stored in data; the list is named groups and contains strings like ‘1’, ‘2’, … id is the Node Id.

const outputHandles = groups.map((group: string, outputIdx: number) => {
    const handleId = `${id}|${outputIdx}`;
    const leftPos = `${((100 / (groups.length + 1)) * (outputIdx + 1))}%`;

    return <Handle
      type="source"
      position={Position.Bottom}
      id={handleId}
      key={handleId}
      style={{ left: leftPos, background: getGroupColor(group) }}
    />;
  });

The Node is generated correctly showing an handle for each group, but when I try to drag a Edge out of the Handle I get this error:

scheduler.development.js:178 Uncaught TypeError: Cannot read property 'find' of null
    at ConnectionLine (cjs.js:12)
    at renderWithHooks (react-dom.development.js:14803)
    at updateFunctionComponent (react-dom.development.js:17034)
    at beginWork (react-dom.development.js:18610)
    at HTMLUnknownElement.callCallback (react-dom.development.js:188)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
    at invokeGuardedCallback (react-dom.development.js:292)
    at beginWork$1 (react-dom.development.js:23203)
    at performUnitOfWork (react-dom.development.js:22154)
    at workLoopSync (react-dom.development.js:22130)
    at performSyncWorkOnRoot (react-dom.development.js:21756)
    at react-dom.development.js:11089
    at unstable_runWithPriority (scheduler.development.js:653)
    at runWithPriority$1 (react-dom.development.js:11039)
    at flushSyncCallbackQueueImpl (react-dom.development.js:11084)
    at flushSyncCallbackQueue (react-dom.development.js:11072)
    at flushPassiveEffectsImpl (react-dom.development.js:22883)
    at unstable_runWithPriority (scheduler.development.js:653)
    at runWithPriority$1 (react-dom.development.js:11039)
    at flushPassiveEffects (react-dom.development.js:22820)
    at react-dom.development.js:22699
    at workLoop (scheduler.development.js:597)
    at flushWork (scheduler.development.js:552)
    at MessagePort.performWorkUntilDeadline (scheduler.development.js:164)

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 24 (11 by maintainers)

Most upvoted comments

Hi Jaspooky, I missed that provider part in doc, it is working now when implemented in children of provider.

When should I call the useUpdateNodeInternals hook? updateNodeInternals(handle_${_transIndex})

updateNodeInternals takes the ID of the node, you are passing the ID of the handle,

I haven’t had time to push that up, but I have it working in my app. I’ll post an updated PR that uses the hook instead in the next day or two.

In v9.1.0 we added a useUpdateNodeInternals hook that can be used to update the node internals programatically.

Usage:

import { useUpdateNodeInternals } from 'react-flow-renderer';

// ....

const updateNodeInternals = useUpdateNodeInternals();

// somewhere in your app
updateNodeInternals('node-id');

Does this solve your issue?

For clarification: We are updating the node internals whenever a node mounts or changes the id, isHidden, sourcePosition or targetPosition option. More over we are observing every node with a ResizeObserver. So when you change the width or height of a node we are also updating it. @burberger came up with the idea to add a MutationOberserver too in #859 but it affects the performance. Now the idea is to create a useUpdateNode hook or an updateNode action to update a specific node.