首页 > 解决方案 > 正确更改反应组件状态

问题描述

我正在一个必须显示图表的项目中工作。为了显示图表,我正在使用 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

在点击节点 2 之前 在点击节点 2 之前

点击节点2后 点击节点2后

更新 1

我在stackblitz创建了一个实时示例,该示例由于我犯的其他故障而无法正常工作并且找不到。

我使用的组件是:

根据xadm提到的一些错误,我重新设计了 MyNetwork 组件。

我实现了两个新函数nodes() 和edges() // 第15-41 行*

现在使用密钥 // 第 18 行 + 32*

第 9 行*

*我上面提到的实时示例中的行号

更新 2

我重新编写了我的代码,现在生活样本正在工作。

我希望我可以使用本机 vis.js 事件并在 MyNetwork 或我将编写的其他组件中使用它们。我在这个问题中读到了关于使用 3rd Party DOM 事件的信息,无法弄清楚它是否适合我的特定情况。因为我不知道如何将事件处理程序附加到 . 是否可以这样做,以便我可以在其他组件中使用该事件?或者我应该为这个主题打开另一个问题?

标签: javascriptreactjs

解决方案


当您单击按钮时,听起来 React 正在重新初始化您的组件。也许比我聪明的人可以弄清楚为什么会这样……

但是由于还没有人对此发表评论,我处理这类问题的一种方法是将状态管理从显示组件中取出。您说您正在通过来自父组件的道具传递节点和边。您可能会考虑将addNoderemoveNodecreateEdge和其他方法移至父组件,以便它保持节点/边缘结构的状态,并且您的显示组件<MyNetwork/>仅显示它作为道具接收的内容。

也许这不是你的应用程序中的一个选项,但我通常使用 Redux 来从组件中删除状态管理。我发现它减少了这样的情况,即“谁应该拥有国家”并不总是很清楚。


推荐阅读