【问题标题】:Alter react component state properly正确更改反应组件状态
【发布时间】:2018-10-29 22:46:36
【问题描述】:

我正在从事一个必须显示图表的项目。 为了显示图表,我特别使用了 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后

更新 1

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

我使用的组件有:

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

  • 组件(尤其是动态的)不应存储在状态中。

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

  • 也应该使用key prop。

现在使用key // line 18 + 32*

  • 传递的props不能修改,还是要复制初始数据
    进入状态。更新/重新渲染需要状态。

第 9 行*

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

更新 2

我重新编写了我的代码,现在生活示例正在运行。

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

【问题讨论】:

  • 你能显示网络组件代码吗?
  • @Morganster 我添加了代码链接

标签: javascript reactjs


【解决方案1】:

我在这里看到了几种可能的问题。

&lt;Decorator/&gt; 应该在&lt;MyNetwork /&gt; 类之外定义。点击处理程序应作为道具传递。

组件(尤其是动态的)不应存储在状态中。只需在渲染中或通过渲染方法(从渲染调用)渲染它们。使用&lt;Node/&gt; 组件和decorator 属性,key 属性也应该使用。

传递的 props 不能被修改,你仍然需要将初始数据复制到 state 中。更新/重新渲染需要状态。您可能需要在删除节点时删除边缘(-es)。

如果问题无法解决,请创建一个工作示例(在 stackblitz 上?)。

【讨论】:

  • 非常感谢您的意见我编辑了我的问题。
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-27
    • 2022-01-18
    • 2019-03-08
    • 1970-01-01
    • 2019-09-17
    • 2020-10-07
    • 1970-01-01
    • 2022-06-27
    相关资源
    最近更新 更多