javascript - React-diagrams 自定义节点小部件未在 engine.repaintCanvas() 上更新
问题描述
我复制了 react-diagrams 演示项目并对 TSCustomNodeWidget.tsx 进行了一些更改,当我调用 engine.repaintCanvas() 时,它不会更新我设置的值(而 DefaultNodeModel 的名称会更新)。
TSCustomNodeModel.ts
import { NodeModel, DefaultPortModel, DefaultNodeModel } from '@projectstorm/react-diagrams';
import { BaseModelOptions } from '@projectstorm/react-canvas-core';
export interface TSCustomNodeModelOptions extends BaseModelOptions {
color?: string;
value?: number;
name?: string;
}
export class TSCustomNodeModel extends DefaultNodeModel {
color: string;
name: string;
value: number;
constructor(options: TSCustomNodeModelOptions = {}) {
super({
...options,
type: 'ts-custom-node'
});
this.color = options.color || 'red';
this.value = options.value || 0;
this.name = options.name || 'name';
// setup an in and out port
this.addPort(
new DefaultPortModel({
in: true,
name: 'IN'
})
);
this.addPort(
new DefaultPortModel({
in: false,
name: 'OUT'
})
);
}
serialize() {
return {
...super.serialize(),
color: this.color
};
}
deserialize(event:any): void {
super.deserialize(event);
this.color = event.data.color;
}
}
TSCustomNodeFactory.tsx
import * as React from 'react';
import { TSCustomNodeModel } from './TSCustomNodeModel';
import { TSCustomNodeWidget } from './TSCustomNodeWidget';
import { AbstractReactFactory } from '@projectstorm/react-canvas-core';
import { DiagramEngine } from '@projectstorm/react-diagrams-core';
export class TSCustomNodeFactory extends AbstractReactFactory<TSCustomNodeModel, DiagramEngine> {
constructor() {
super('ts-custom-node');
}
generateModel(initialConfig:any) {
return new TSCustomNodeModel();
}
generateReactWidget(event:any): JSX.Element {
return <TSCustomNodeWidget engine={this.engine as DiagramEngine} node={event.model} />;
}
}
TSCustomNodeWidget.tsx
import * as React from 'react';
import { DiagramEngine, PortWidget } from '@projectstorm/react-diagrams-core';
import { TSCustomNodeModel } from './TSCustomNodeModel';
export interface TSCustomNodeWidgetProps {
node: TSCustomNodeModel;
engine: DiagramEngine;
}
export interface TSCustomNodeWidgetState {}
export class TSCustomNodeWidget extends React.Component<TSCustomNodeWidgetProps, TSCustomNodeWidgetState> {
constructor(props: TSCustomNodeWidgetProps) {
super(props);
this.state = {};
}
render() {
return (
<div className="custom-node">
<PortWidget engine={this.props.engine} port={this.props.node.getPort('IN')}>
<div className="circle-port" />
</PortWidget>
<PortWidget engine={this.props.engine} port={this.props.node.getPort('OUT')}>
<div className="circle-port" />
</PortWidget>
<div className="custom-node-color"
style={{ backgroundColor: this.props.node.color }}>
{this.props.node.value}
</div>
</div>
);
}
}
App.tsx 设置
// create an instance of the engine with all the defaults
const engine = createEngine();
const state = engine.getStateMachine().getCurrentState();
if (state instanceof DefaultDiagramState) {
state.dragNewLink.config.allowLooseLinks = false;
}
const model = new DiagramModel();
engine.getNodeFactories().registerFactory(new TSCustomNodeFactory());
model.setGridSize(5);
engine.setModel(model);
使用按钮添加节点(repaintCanvas 有效)
function addConstNode() {
const node = new TSCustomNodeModel({
name: "CONST",
value: 0
});
node.setPosition(50, 50);
model.addAll(node);
engine.repaintCanvas(); //This works
return node;
}
更新节点(repaintCanvas 不起作用)
currentNode.value = value;
...
engine.repaintCanvas();
解决方案
I had a similar issue, where changing nodes would not update canvas immediately, and I managed to get around it by forcing the react component to re-render by doing this:
function useForceUpdate(){
const [, setValue] = useState(0);
return () => setValue(value => ++value);
}
const MyComponent = () => {
const forceUpdate = useForceUpdate();
// do some update to diagram
...
forceUpdate();
};
Can't remember if I also had to call engine.repaintCanvas() also or not.
Bit late to the party but hope this helps.
推荐阅读
- react-native - React Native浮动操作按钮可触摸不起作用
- sql - Oracle SQL 条件求和
- laravel - Laravel 火花资源的 Spatie 权限
- sapui5 - 如何在我的控制器中使用选择控件?
- spring-mvc - 在 spring mvc portlet 中找不到“beans”元素的声明
- r - R:`lubridate` 在 Windows 中无法识别时区“SG”
- wpf - 列表框中的自我工具提示
- python - 根据现有列更新 pandas 中的滚动窗口值
- c# - 如何在两个导航属性上执行包含,两者都可能获得相同的引用?
- extjs - extjs如何确定用户是否触发了组合框更改事件