代码之家  ›  专栏  ›  技术社区  ›  andreask

正确改变组件状态

  •  1
  • andreask  · 技术社区  · 7 年前

    对于显示图形,我特别使用vis.js react-vis-network 在React中使用vis.js部分的一个实现,它使用有状态的方法。

    我附加了两个eventHandler,一个直接连接到vis.js(底层DOM库),另一个连接到decorator(按钮)。

    期望/预期行为:

    观察到的行为: 有时一个节点被移除,有时一个节点仅仅消失了几毫秒,然后被重新连接,但没有装饰器/按钮。

    我已经尝试从空状态开始,并在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之前 Before clicking node 2

    单击节点2后 After clicking node 2

    更新1

    实例 stackblitz 因为其他的失败我都找不到,所以现在还不起作用。

    我根据一些错误修改了MyNetwork组件 xadm公司

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

    • 关键道具也应该使用。

    • 传递的道具不能修改,仍需复制初始数据
      进入状态。状态是更新/重新提交所必需的。

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

    我重新编写了我的代码,现在生命样本开始工作了。

    我希望我能利用这个机会 在我的网络或其他我要写的组件中使用它们。 我在这篇文章中读到了关于使用第三方DOM事件的内容 question 我想不出如何适应我的特殊情况。因为我不知道如何将事件处理程序附加到。这样我就可以在其他组件中使用事件了吗? 或者我应该为这个话题再问一个问题?

    2 回复  |  直到 7 年前
        1
  •  1
  •   xadm    7 年前

    <Decorator/> <MyNetwork /> 班级。单击处理程序应作为属性传递。

    <Node/> decorator 道具, key 道具也应该用。

        2
  •  1
  •   nbwoodward    7 年前

    当您单击按钮时,React似乎正在重新初始化您的组件。也许比我聪明的人能弄明白为什么会这样。。。

    但是由于还没有人对此发表评论,我处理这类问题的一种方法是将状态管理从显示组件中去掉。您说您是通过来自父零部件的道具传递节点和边。你可以考虑搬家 addNode removeNode , createEdge <MyNetwork/> 只显示它作为道具收到的东西。