react-diagrams icon indicating copy to clipboard operation
react-diagrams copied to clipboard

Node not getting added with useEffect

Open abhisheksarka opened this issue 1 year ago • 3 comments

Hi,

I have been trying to make this work with useEffect as follows

import createEngine, { 
  DefaultLinkModel, 
  DefaultNodeModel,
  DefaultLabelModel,
  DiagramModel, 
  LabelModel
} from '@projectstorm/react-diagrams';
import { useSelector } from 'react-redux'
import styles from './Diagram.module.scss';

import {
  CanvasWidget
} from '@projectstorm/react-canvas-core';
import styled from '@emotion/styled';
import { useEffect } from 'react';
import { drawEdge, drawNode } from './reducer';

const FullscreenCanvas = styled(CanvasWidget)`
  height: 100%;
  width: 100%;
`;

export default function Diagram(props) {
  const nodes = useSelector((state) => state.nodes);
  const engine = createEngine();
  const model = new DiagramModel();
  engine.setModel(model);

  useEffect(() => {
    nodes.forEach(node => {
      addNode({
        name: node.name,
        color: 'rgb(0,192,255)'
      })
    });

    engine.repaintCanvas();
  }, [nodes]);

  function addNode(attrs) {
    const node = new DefaultNodeModel(attrs);
    node.setPosition(100, 100);
    model.addAll(node); 
  }

  return (
    <>
      <div className={styles['diagram-container']}>
        <FullscreenCanvas engine={engine} />
      </div>
    </>
    
  )
}

Instead of useEffect if I call addNode function onClick of a button and then repaintCanvas, it works

Is anything extra required in case of useEffect? Thanks in advance!

abhisheksarka avatar Dec 04 '22 19:12 abhisheksarka

Seems like everything is ok in your example, so my theory is that there are problems with redux. If you have not solved the problem yet, you can send a link to a sandbox.

Marshall200900 avatar Dec 06 '22 13:12 Marshall200900

what type is nodes?

if it is an array or object the dependency array will use referential comparison. so if you did not swap the object and instead just mutated it, the effect may not be running.

quick fix:

use [JSON.stringify(nodes)] in the dep array

vxlk avatar Jan 13 '23 15:01 vxlk

I've got it working with a useRef

...
const engine = createEngine();
const model = useRef(new DiagramModel());
engine.setModel(model.current);
...

then when you need to interact with model from a hook then you can:

model.current.addAll(node);

jameswest368 avatar Mar 01 '23 17:03 jameswest368