Hey first I just wanted to say thank you so much for your time, and looking into this so in depth. I've simplified the component a bit more for now:
export interface KanoaDiagramProps {
diagramSchema: any;
test: string;
onChange?: any;
}
const initialSchema = createSchema({
nodes: [
{ id: 'node-1', content: 'Node 1', coordinates: [250, 60], inputs: [], outputs: []},
{ id: 'node-2', content: 'Node 2', coordinates: [100, 200], inputs: [], outputs: []},
{ id: 'node-3', content: 'Node 3', coordinates: [250, 220], inputs: [], outputs: []},
{ id: 'node-4', content: 'Node 4', coordinates: [400, 200], inputs: [], outputs: []},
],
links: [
{ input: 'node-1', output: 'node-2' },
{ input: 'node-1', output: 'node-3' },
{ input: 'node-1', output: 'node-4' },
]
});
export class KanoaDiagramMeta implements ComponentMeta {
getComponentType(): string {
return COMPONENT_TYPE;
}
getViewComponent(): PComponent {
return KanoaDiagram;
}
getDefaultSize(): SizeObject {
return ({
width: 475,
height: 200
});
}
getPropsReducer(tree: PropertyTree): KanoaDiagramProps {
return {
diagramSchema: tree.readObject("diagramSchema"),
test: tree.readString("nodes", "default"),
onChange: tree.read("onChange"),
};
}
}
export function KanoaDiagram(props: ComponentProps<KanoaDiagramProps>) {
const [schema, { addNode, removeNode, onChange }] = useSchema(initialSchema);
const [diagramSchema, setDiagramSchema] = useState(initialSchema);
const CustomRender = ({ id, content, data, inputs, outputs }) => (
<div>
<div role="button" style={{padding: '15px'}}>
{content}
</div>
<div style={{marginTop: '10px',display:'flex', justifyContent:'space-between'}}>
{inputs.map((port) => React.cloneElement(port))}
{outputs.map((port) => React.cloneElement(port))}
</div>
</div>
);
const deleteNodeFromSchema = (id) => {
const nodeToRemove = schema.nodes.find(node => node.id === id)!;
removeNode(nodeToRemove)
};
const addNewNode = () => {
const coord: NodeCoordinates = [
schema.nodes[schema.nodes.length - 1].coordinates[0] + 100,
schema.nodes[schema.nodes.length - 1].coordinates[1],
];
const nextNode = {
id: `node-${schema.nodes.length+1}`,
content: `Node ${schema.nodes.length+1}`,
coordinates: coord,
render: CustomRender,
className: 'bi-diagram-node-default',
data: {onClick: deleteNodeFromSchema},
inputs: [{ id: `port-${Math.random()}`}],
outputs: [{ id: `port-${Math.random()}`}],
}!;
addNode(nextNode);
setDiagramSchema(schema);
const updatedConvertSchema = JSON.parse(JSON.stringify(schema));
props.store.props.write('diagramSchema', new QualifiedValue(updatedConvertSchema));
props.store.props.write('text', String(schema.nodes.length));
};
const UncontrolledDiagram = () => {
return (
<div style={{ height: '100%' }}>
{/* <button onClick={addNewNode}>Add new node</button> */}
<Diagram schema={diagramSchema} onChange={onChange} />
</div>
);
};
return (
<div {...props.emit()}>
{/* <div ref={diagramRef} /> */}
<button onClick={() => {
addNewNode();
props.store.props.write("diagramSchema", diagramSchema);
}}>Add new node</button>
<div>{JSON.stringify(diagramSchema)}</div>
<UncontrolledDiagram />
<ReactResizeDetector
handleHeight={ true }
handleWidth={ true }
refreshMode="debounce"
/>
</div>
);
}
Your suggestion didn't work out unfortunately, and in fact I'm getting the same error when I just try to do a write to a simple string property called 'text'. So there's a more pressing issue than just the type of prop I'm trying to write to, I think. I've additionally added an additional attempt to write to the propertyTree in the button onClick at the bottom with no response either.
For some reason it just seems like props.write() never really goes through for me, and I've confirmed that what I'm passing in should be an updated schema.
What I've found is that my diagramSchema prop starts out empty because I never initialized it to anything yet, properly updates to include the schema with the initial 4 nodes, but then never again updates on subsequent addNewNode calls. Meanwhile I've confirmed that the 'schema' and 'diagramSchema' variables update every time correctly.
Edit: also provided the interface props, initialSchema, and the meta class for the full picture