projectstorm / react-diagrams

a super simple, no-nonsense diagramming library written in react that just works
https://projectstorm.cloud/react-diagrams
MIT License
8.71k stars 1.18k forks source link

Uncaught TypeError. Cannot read property 'offsetWidth' of null in PathFindingLinkFactory calculateMatrixDimensions #671

Open flieks opened 4 years ago

flieks commented 4 years ago

Getting this error when doing a recalc of the engine with all nodes.

image

stacktrace: PathFindingLinkFactory.tsx:206 Uncaught TypeError: Cannot read property 'offsetWidth' of null at PathFindingLinkFactory._this.calculateMatrixDimensions (PathFindingLinkFactory.tsx:206) at PathFindingLinkFactory.calculateCanvasMatrix (PathFindingLinkFactory.tsx:101) at PathFindingLinkFactory.getCanvasMatrix (PathFindingLinkFactory.tsx:96) at PathFindingLinkFactory.calculateRoutingMatrix (PathFindingLinkFactory.tsx:142) at PathFindingLinkFactory.tsx:58 at lodash.js:2750

So it is probably on this line where canvas is null const maxX = Math.max(sumProps(maxXElement, ['x', 'width']), canvas.offsetWidth);

FavorMylikes commented 4 years ago

It only happens when you want to call calculateRoutingMatrix before dom render

pSnehanshu commented 4 years ago

How do I know if the dom has been rendered or not? It probably has rendered, because I am returning JSX from the components.

FavorMylikes commented 4 years ago

From my experience, there is two ways to implement it. One of them is setInterval wait 200ms, in most of times, it works, or, use some third lib to monitor the dom finish. But I'll suggest do not call reroute or some other function that depend on calculateRoutingMatrix in render function. And add width and height in state as args.

We can look deep inside. const maxX = Math.max(sumProps(maxXElement, ['x', 'width']), canvas.offsetWidth); This line is trying getting the width from canvas. and as the same time, the width is come from other config that like browser page or other Component states. So why don't you try to set it in your own Component.

Any way, if there's any better way, glad to hear it.

pSnehanshu commented 4 years ago

@FavorMylikes Yes, there is a better way. react-diagrams is full of meaningless edge cases, hence it is better to completely avoid this library if you don't want to burn out. I will recommend https://www.npmjs.com/package/react-flow-renderer as an alternative.

FavorMylikes commented 4 years ago

Oh, cool, I'll try to integrate dagre

Omario-r commented 3 years ago

This works for me:

function Diagram() {
  const [engine, setEngine] = useState()

  useEffect(() => {
    const engine = createEngine();
    /*  operations with engine */
    setEngine(engine)
  }, [])

  return (
    <div>
      {engine && <CanvasWidget engine={engine} />}
    </div>
  );
}