javascript - 正确更改反应组件状态
问题描述
我正在一个必须显示图表的项目中工作。为了显示图表,我正在使用 vis.js,特别是react-vis-network一个实现,用于在 React 中使用 vis.js 的一部分及其有状态的方法。
在我的组件安装之前加载初始节点和边,并作为初始状态的道具传递。
我将两个 eventHandler 一个直接连接到 vis.js(底层 DOM 库),另一个连接到装饰器(按钮)。
期望的/预期的行为: 通过单击节点或相应的按钮来删除节点。
观察到的行为: 有时一个节点被删除,有时一个节点只是消失了几毫秒,然后重新连接,但没有装饰器/按钮。
我已经尝试从一个空状态开始并在 componentDidMount() 中附加节点、边缘,但我得到了相同的结果。我希望你能给我一个提示。顺便说一句:我用来连接组件的方式是正确的吗? 对提高我的课堂水平的所有其他帮助也值得赞赏
class MyNetwork extends Component {
constructor(props){
super(props);
let componentNodes = [];
for (let node of props.nodes){
componentNodes.push(this.createNode(node));
}
let componentEdges = [];
for (let edge of props.edges){
componentEdges.push(this.createEdge(edge));
}
this.state = {nodes:componentNodes,edges:componentEdges};
["_handleButtonClick"].forEach(name => {
this[name] = this[name].bind(this);
});
}
createNode(node){
const Decorator = props => {
return (
<button
onClick={() =>{this._handleButtonClick(props);}}
>
Click Me
</button>
);
};
node.decorator = Decorator;
return React.createElement(Node,{...node})
}
createEdge(edge){
return React.createElement(Edge,{...edge})
}
addNode(node){
this.setState({
nodes: [...this.state.nodes, this.createNode(node)]
})
}
_handleButtonClick(e) {
if(e){
console.log("clicked node has id:" +e.id);
this.removeNode(e.id);
}
}
onSelectNode(params){
console.log(params);
window.myApp.removeNode(params[0]);
}
removeNode(id) {
let array = [...this.state.nodes]; // make a separate copy of the array
let index = array.findIndex(i => i.props.id === id );
array.splice(index, 1);
this.setState({nodes: array});
}
render() {
return (
<div id='network'>
<Network options={this.props.options} onSelectNode={this.onSelectNode}>
{[this.state.nodes]}
{[this.state.edges]}
</Network>
</div>
);
}
}
export default MyNetwork
更新 1
我在stackblitz创建了一个实时示例,该示例由于我犯的其他故障而无法正常工作并且找不到。
我使用的组件是:
根据xadm提到的一些错误,我重新设计了 MyNetwork 组件。
组件(特别是动态的)不应存储在状态中。
我实现了两个新函数nodes() 和edges() // 第15-41 行*
也应该使用 key prop。
现在使用密钥 // 第 18 行 + 32*
传递的 props 不能被修改,你仍然需要将初始数据复制
到 state 中。更新/重新渲染需要状态。
第 9 行*
*我上面提到的实时示例中的行号
更新 2
我重新编写了我的代码,现在生活样本正在工作。
我希望我可以使用本机 vis.js 事件并在 MyNetwork 或我将编写的其他组件中使用它们。我在这个问题中读到了关于使用 3rd Party DOM 事件的信息,无法弄清楚它是否适合我的特定情况。因为我不知道如何将事件处理程序附加到 . 是否可以这样做,以便我可以在其他组件中使用该事件?或者我应该为这个主题打开另一个问题?
解决方案
当您单击按钮时,听起来 React 正在重新初始化您的组件。也许比我聪明的人可以弄清楚为什么会这样……
但是由于还没有人对此发表评论,我处理这类问题的一种方法是将状态管理从显示组件中取出。您说您正在通过来自父组件的道具传递节点和边。您可能会考虑将addNode
、removeNode
、createEdge
和其他方法移至父组件,以便它保持节点/边缘结构的状态,并且您的显示组件<MyNetwork/>
仅显示它作为道具接收的内容。
也许这不是你的应用程序中的一个选项,但我通常使用 Redux 来从组件中删除状态管理。我发现它减少了这样的情况,即“谁应该拥有国家”并不总是很清楚。
推荐阅读
- postgresql - “org.hibernate.PersistentObjectException:分离的实体传递给持久化”错误经过大量研发后没有得到解决
- swift - 核心数据数据删除
- jquery - 可变高度水平手风琴
- git - 每当在远程分支中完成 git 提交时,如何生成电子邮件?
- graphics - BlueSky Statistics 中的图形图像大小
- javascript - HTML 滚动到 div 菜单
- kentico - 电子邮件主题编码
- php - 如何从数据库中选择多个值
- tfs - 自动从 TFS 的包含更改中排除特定文件
- amazon-web-services - Boto3 使用新的 s3 输入启动胶水爬虫