I need make a stateless functional component in react and I want to use ReactDiagram component .the below code was i got as an minimal example . I got some hooks issue while implementing in react. please mention if there was any example of functional component and stateless.
import React from 'react';
import * as go from 'gojs';
import './App.css';
function App() {
var $ = go.GraphObject.make; // for conciseness in defining templates
var myDiagram = $(go.Diagram, "myDiagramDiv", // create a Diagram for the DIV HTML element
{
"undoManager.isEnabled": true // enable undo & redo
});
// define a simple Node template
myDiagram.nodeTemplate =
$(go.Node, "Auto", // the Shape will go around the TextBlock
$(go.Shape, "RoundedRectangle", { strokeWidth: 0, fill: "white" },
// Shape.fill is bound to Node.data.color
new go.Binding("fill", "color")),
$(go.TextBlock,
{ margin: 8, font: "bold 14px sans-serif", stroke: '#333' }, // Specify a margin to add some room around the text
// TextBlock.text is bound to Node.data.key
new go.Binding("text", "key"))
);
// but use the default Link template, by not setting Diagram.linkTemplate
// create the model data that will be represented by Nodes and Links
myDiagram.model = new go.GraphLinksModel(
[
{ key: "Alpha", color: "lightblue" },
{ key: "Beta", color: "orange" },
{ key: "Gamma", color: "lightgreen" },
{ key: "Delta", color: "pink" }
],
[
{ from: "Alpha", to: "Beta" },
{ from: "Alpha", to: "Gamma" },
{ from: "Beta", to: "Beta" },
{ from: "Gamma", to: "Delta" },
{ from: "Delta", to: "Alpha" }
]);
return (
<div id='myDiagramDiv' style={{width:'600px',height:'600px',border:'1px solid black'}}/>
);
}
export default App;
However you presumably do want your diagram to show the data that comes in via props, and to update when the props have changed. The problem is that there is potentially a lot of overhead in creating, initializing, and rendering a diagram, so one really would prefer not to re-create the diagram each time. That’s why the gojs-react ReactDiagram component is implemented the way that it is.
this thing is not about the permission or some else,
wheter react hooks can be used in gojs?, if yes how we could proceed
and need to do without the <ReactDiagram/> component, if it can be done by Diagram API ,how do I merge with stateless functional component
public handleDiagramEvent(e: go.DiagramEvent) {
const name = e.name;
switch (name) {
case 'ChangedSelection': {
const sel = e.subject.first();
this.setState(
produce((draft: AppState) => {
if (sel) {
if (sel instanceof go.Node) {
const idx = this.mapNodeKeyIdx.get(sel.key);
if (idx !== undefined && idx >= 0) {
const nd = draft.nodeDataArray[idx];
draft.selectedData = nd;
}
} else if (sel instanceof go.Link) {
const idx = this.mapLinkKeyIdx.get(sel.key);
if (idx !== undefined && idx >= 0) {
const ld = draft.linkDataArray[idx];
draft.selectedData = ld;
}
}
} else {
draft.selectedData = null;
}
})
);
break;
}
default: break;
}
}
/**
* Handle GoJS model changes, which output an object of data changes via Model.toIncrementalData.
* This method iterates over those changes and updates state to keep in sync with the GoJS model.
* @param obj a JSON-formatted string
*/
public handleModelChange(obj: go.IncrementalData) {
const insertedNodeKeys = obj.insertedNodeKeys;
const modifiedNodeData = obj.modifiedNodeData;
const removedNodeKeys = obj.removedNodeKeys;
const insertedLinkKeys = obj.insertedLinkKeys;
const modifiedLinkData = obj.modifiedLinkData;
const removedLinkKeys = obj.removedLinkKeys;
const modifiedModelData = obj.modelData;
// maintain maps of modified data so insertions don't need slow lookups
const modifiedNodeMap = new Map<go.Key, go.ObjectData>();
const modifiedLinkMap = new Map<go.Key, go.ObjectData>();
this.setState(
produce((draft: AppState) => {
let narr = draft.nodeDataArray;
if (modifiedNodeData) {
modifiedNodeData.forEach((nd: go.ObjectData) => {
modifiedNodeMap.set(nd.key, nd);
const idx = this.mapNodeKeyIdx.get(nd.key);
if (idx !== undefined && idx >= 0) {
narr[idx] = nd;
if (draft.selectedData && draft.selectedData.key === nd.key) {
draft.selectedData = nd;
}
}
});
}
if (insertedNodeKeys) {
insertedNodeKeys.forEach((key: go.Key) => {
const nd = modifiedNodeMap.get(key);
const idx = this.mapNodeKeyIdx.get(key);
if (nd && idx === undefined) { // nodes won't be added if they already exist
this.mapNodeKeyIdx.set(nd.key, narr.length);
narr.push(nd);
}
});
}
if (removedNodeKeys) {
narr = narr.filter((nd: go.ObjectData) => {
if (removedNodeKeys.includes(nd.key)) {
return false;
}
return true;
});
draft.nodeDataArray = narr;
this.refreshNodeIndex(narr);
}
let larr = draft.linkDataArray;
if (modifiedLinkData) {
modifiedLinkData.forEach((ld: go.ObjectData) => {
modifiedLinkMap.set(ld.key, ld);
const idx = this.mapLinkKeyIdx.get(ld.key);
if (idx !== undefined && idx >= 0) {
larr[idx] = ld;
if (draft.selectedData && draft.selectedData.key === ld.key) {
draft.selectedData = ld;
}
}
});
}
if (insertedLinkKeys) {
insertedLinkKeys.forEach((key: go.Key) => {
const ld = modifiedLinkMap.get(key);
const idx = this.mapLinkKeyIdx.get(key);
if (ld && idx === undefined) { // links won't be added if they already exist
this.mapLinkKeyIdx.set(ld.key, larr.length);
larr.push(ld);
}
});
}
if (removedLinkKeys) {
larr = larr.filter((ld: go.ObjectData) => {
if (removedLinkKeys.includes(ld.key)) {
return false;
}
return true;
});
draft.linkDataArray = larr;
this.refreshLinkIndex(larr);
}
// handle model data changes, for now just replacing with the supplied object
if (modifiedModelData) {
draft.modelData = modifiedModelData;
}
draft.skipsDiagramUpdate = true; // the GoJS model already knows about these updates
})
);
}
/**
* Handle inspector changes, and on input field blurs, update node/link data state.
* @param path the path to the property being modified
* @param value the new value of that property
* @param isBlur whether the input event was a blur, indicating the edit is complete
*/
public handleInputChange(path: string, value: string, isBlur: boolean) {
this.setState(
produce((draft: AppState) => {
const data = draft.selectedData as go.ObjectData; // only reached if selectedData isn't null
data[path] = value;
if (isBlur) {
const key = data.key;
if (key < 0) { // negative keys are links
const idx = this.mapLinkKeyIdx.get(key);
if (idx !== undefined && idx >= 0) {
draft.linkDataArray[idx] = data;
draft.skipsDiagramUpdate = false;
}
} else {
const idx = this.mapNodeKeyIdx.get(key);
if (idx !== undefined && idx >= 0) {
draft.nodeDataArray[idx] = data;
draft.skipsDiagramUpdate = false;
}
}
}
})
);
}
you can see here the setState method, I need to do with React hooks
nearly I did something on that now the Diagram API call only not working well
I want to know while we calling Diagram API from an React app which props are mandatory
like nodeDataArray,linkDataArray
That depends on which features of GoJS you are using. As a practical matter, I would say that the initDiagram and nodeDataArray are essential, and linkDataArray is essential if you are using a GraphLinksModel.
but how do I define initDiagram(),onModelChange(),onDiagramChange(),ModelData
these stuffs
I’m searching for an valid working example of using Diagram API in react but I found nothing useful, please refer any example for quick understanding purpose
Oh, I thought you were using the ReactDiagram component in gojs-react. OK, so I assume you are constructing something yourself using React functional components rather than React classes.
By initDiagram I was referring to the function used to create and initialize the Diagram associated with the HTMLDivElement. That means allocating the Diagram, setting its properties, and setting up its templates and tools and whatever.
But as I said above, I do not think you want to have a pure stateless diagram, because you do not want to re-create and re-initialize the Diagram on each render. For large diagrams that should be obvious, but even for tiny diagrams such re-creation seems quite wasteful. There is a reason that in gojs-react we override shouldComponentUpdate and componentDidUpdate.
Here’s a very basic example demonstrating how you can use a ReactDiagram within a functional component. I’m not sure if this is exactly what you’re looking for, but it serves to demonstrate that gojs-react can be used in the context of React hooks.
yeah it is very useful but I need an example of without using <ReactDiagram/> component
var myDiagram = $(go.Diagram, "myDiagramDiv", // create a Diagram for the DIV HTML element
{
"undoManager.isEnabled": true // enable undo & redo
});
// define a simple Node template
myDiagram.nodeTemplate =
$(go.Node, "Auto", // the Shape will go around the TextBlock
$(go.Shape, "RoundedRectangle", { strokeWidth: 0, fill: "white" },
// Shape.fill is bound to Node.data.color
new go.Binding("fill", "color")),
$(go.TextBlock,
{ margin: 8, font: "bold 14px sans-serif", stroke: '#333' }, // Specify a margin to add some room around the text
// TextBlock.text is bound to Node.data.key
new go.Binding("text", "key"))
);
// but use the default Link template, by not setting Diagram.linkTemplate
// create the model data that will be represented by Nodes and Links
myDiagram.model = new go.GraphLinksModel(
[
{ key: "Alpha", color: "lightblue" },
{ key: "Beta", color: "orange" },
{ key: "Gamma", color: "lightgreen" },
{ key: "Delta", color: "pink" }
],
[
{ from: "Alpha", to: "Beta" },
{ from: "Alpha", to: "Gamma" },
{ from: "Beta", to: "Beta" },
{ from: "Gamma", to: "Delta" },
{ from: "Delta", to: "Alpha" }
]);
return (
<div id='myDiagramDiv' style={{width:'600px',height:'600px',border:'1px solid black'}}/>
);