Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
199 views
in Technique[技术] by (71.8m points)

reactjs - Building a unidirectional graph in React

I have a use case where I need to build a unidirectional graph, which basically explains the dependency of the child node to it's parent node and so on....

For a corresponding input(one root node), multiple child nodes and sub child nodes need to be rendered on the screen in the form of a graph

Any suggestions to which library I can use to fulfil this.

I dont know how many children would be there for each root node, so giving specific coordinates in the 2d space would be quite cumbersome. I'll be getting the input data in the form of a json for which I need to build the graph

Example

enter image description here

Flowpoints library (flowpoints npm) is the one I saw until now which can do something like this, but if anyone has a better suggestion

question from:https://stackoverflow.com/questions/65936885/building-a-unidirectional-graph-in-react

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Use React-Flow with dagre. Dagre automatically positions nodes for the graph. Sample code below. Also check out the website https://reactflow.dev/docs/

 import React, { useState, useCallback } from 'react';
    import ReactFlow, {
    ReactFlowProvider,
    addEdge,
    removeElements,
    isNode,
    } from 'react-flow-renderer';
    import dagre from 'dagre';


    class LayoutFlow extends React.Component{
      constructor(props){
        super(props)
        this.state = {
          elements : []
        }
      }
    
      componentDidMount(){
        const position = { x: 0, y: 0 };
        const edgeType = 'smoothstep';
        const array = [{id:"1",data:"node 1",output:["2","3"]},{id:"2",data:"node 2",output:["2a","2b","2c"]},{id:"3",data:"node 3"},
        {id:"2a",data:"node 2a"},{id:"2b",data:"node 2b"},{id:"2c",data:"node 2c",output:["2d"]},{id:"2d",data:"node 2d"}
      ]
        const newArray = []
        const k = 0
        array.map((ele,i) => {
          newArray.push({id:ele.id,data:{label:<div><h3>{ele.data}</h3><h4>This is a node</h4></div>},position, connectable:false})
        })
        array.map((ele,i) => {
          if(ele.output !== undefined && ele.output !== null){
            ele.output.map((element,p) => {
              newArray.push({id:"e"+ele.id+element,source:ele.id,target:element,type: edgeType})
            })
          }
        })
        this.setState({ elements : newArray}, () =>{
    
          const dagreGraph = new dagre.graphlib.Graph();
    dagreGraph.setDefaultEdgeLabel(() => ({}));
    const getLayoutedElements = (elements, direction = 'TB') => {
      const isHorizontal = direction === 'LR';
      dagreGraph.setGraph({ rankdir: direction });
      elements.forEach((el) => {
        if (isNode(el)) {
          dagreGraph.setNode(el.id, { width: 300, height: 150 });
        } else {
          dagreGraph.setEdge(el.source, el.target);
        }
      });
      dagre.layout(dagreGraph);
      return elements.map((el) => {
        if (isNode(el)) {
          const nodeWithPosition = dagreGraph.node(el.id);
          el.targetPosition = isHorizontal ? 'left' : 'top';
          el.sourcePosition = isHorizontal ? 'right' : 'bottom';
          el.position = {
            x: nodeWithPosition.x + Math.random() / 1000,
            y: nodeWithPosition.y,
          };
        }
        return el;
      });
    };
    const layoutedElements = getLayoutedElements(this.state.elements);
    
        })
      }
    
      onConnect = (params) =>{
        this.setState((els) =>
        addEdge({ ...params, type: 'smoothstep'}, els))
      }
    
      render(){
        return (
          <div className="layoutflow" style={{width:10000,height:10000}}>
            <ReactFlowProvider>
              <ReactFlow
                elements={this.state.elements}
                onConnect={this.onConnect}
                connectionLineType="smoothstep"
              />
            </ReactFlowProvider>
          </div>
        );
      }
    
    }
    export default LayoutFlow;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...