当前位置: 首页 > 知识库问答 >
问题:

无法从React js中深度嵌套的子节点更新父节点的状态

东郭鹤龄
2023-03-14

我正在尝试使用react组件递归地构造树(json对象)的一些SVG。每个节点(树的节点)组件都返回其他节点(和边),直到不再有子节点为止。这棵树在我的屏幕上呈现得非常完美。

现在我想用一个函数来计算所有的叶节点,我通过道具传递给所有的节点。当一个节点没有子节点时,它会调用其构造函数中的函数。有了这个功能,我想使用this.set状态增加我主要组件的this.state.count叶。这个函数被调用的频率和我的树中有叶子节点一样高(我正在用console.log检查它)。对于每个叶节点,函数被调用,但我的状态不更新。

我的主要组成部分:

import React, { Component } from 'react';
import SpecNode from './graphicTreeComponents/SpecNode.js';

class GraphicController extends Component {
    constructor(props){
        super(props);
        this.incLeafs = this.incLeafs.bind(this);

        this.state = ({
            u: {key: "0", x: 100, y: 0, k: 
                    [
                    {key: "1", x: 40, y: 100, k: null},
                    {key: "2", x: 160, y: 100, k: null}
                    ]
                },
            countLeafs: 0
        })
    }
    incLeafs(){
        console.log("leafs++");
        this.setState({countLeafs: this.state.countLeafs + 1});
        console.log(this.state.countLeafs);
    }
    render(props){
        return (
            <div className="GraphicController">
                <SpecNode {...this.state.u} incLeafs={this.incLeafs}/>
            </div>
        );
    }
}
export default GraphicController;

和我的节点组件:

import React, { Component } from 'react';
import Edge from './Edge.js';
import SpecNode2 from './SpecNode.js';

class SpecNode extends Component{

    constructor(props){
        super(props);

        if(!this.props.k){
            this.props.incLeafs();
        }
    }

    render(props){
        return(
            <svg>
                {this.props.k ? 
                    this.props.k.map(e =>
                        <svg>
                            <Edge x1={this.props.x} y1={this.props.y} x2={e.x} y2={e.y} />
                            <SpecNode2 {...e} incLeafs={this.props.incLeafs}/>
                            <circle cx={e.x} cy={e.y} r={5} fill={"lightgrey"} />
                            <text fontSize={7} x={e.x-2} y={e.y+3} fill="black">{e.key}</text>
                        </svg>
                    ) 
                    :
                    null
                }
            </svg>
        );
    }
}
export default SpecNode;

有什么我错过的吗?

非常感谢。

共有2个答案

上官鸿祯
2023-03-14

您的方法this.incLeafs未绑定到父组件。因此,当它运行时,this并不意味着子节点调用该方法时的GraphicController

任何一个

A) 更改将父类上的方法写入arrow函数的方式,如下所示:incLeafs=()=

B) 在某个点手动绑定method方法,例如使用this.incLeafsHandler=this.incLeafs.bind(this),然后将this.incLeafsHandler作为incLeaf回调传递给SpecNode。((我非常不喜欢这个解决方案,但这只是我的偏好。)

C),在道具中作为箭头函数向下传递(如

箭头函数总是保留this,无论它是什么,当箭头函数被声明。(备选方案A和C)

普通函数将根据调用它们的位置更改this,除非您使用原始方法的绑定副本。(备选案文B)

别永年
2023-03-14

你确定leafCount没有更新吗?setState是异步的,但需要回调。您的console.log可能在状态更新之前发生。你应该试试像。。。

incLeafs(){
    console.log("leafs++");
    this.setState({countLeafs: this.state.countLeafs + 1}, () => {
        console.log(this.state.countLeafs);
    });   
}

在主组件中,初始化状态时不需要括号。

this.state = {
        u: {key: "0", x: 100, y: 0, k: 
                [
                {key: "1", x: 40, y: 100, k: null},
                {key: "2", x: 160, y: 100, k: null}
                ]
            },
        countLeafs: 0
    }

您还可以尝试将您的函数调用移动到SpecNode组件中的组件

constructor(props){
    super(props);
}
componentDidMount() {
    if(!this.props.k){
        this.props.incLeafs();
    }
}
 类似资料:
  • 我想用XSLT转换XML文档。按名称和属性匹配的节点及其子节点应嵌套/移动到新节点中。 从转变 到 但是我的XSLT工作不好。您有什么提示吗,XSLT文件有什么问题? 非常感谢你 安德烈亚斯 我的XSLT 输出: 我的源XML文件 我希望在转换后的输出中将v:data节点及其子节点嵌套到一个新节点中。但只有属性名为“Custon”的v:data节点。转换后的XML文档应该如下所示 如果我从XSLT

  • 我想从父节点复制到子节点。我真的不确定这是如何实现的。 我的源xml 我想得到输出为 我想要XSLT1.0中的解决方案。 我想将这些节点复制到子节点 谢谢。

  • 我需要将子元素复制到父元素中。 输入 期望输出 我尝试的内容(输出与输入保持相同): 我肯定会错过一些非常简单的事情。子元素与父元素具有相同的名称,这应该不是问题?

  • 我正在用flexbox做实验,并创建了这个布局。我试图让中间写着“嘿”的白色方框成为父方框的90%宽度/高度,但百分比似乎不会影响它。(我把它设置为100px/100px目前工作) 这很奇怪,因为父节点在检查时有一个定义的宽度/高度。 有人能告诉我如何实现吗?(此外,对我如何使用flexbox的一般批评也很赞赏) http://jsfiddle.net/yv3Lw5gy/1/ 相关类别:

  • 如果我没弄错的话,树通常是一个列表,其中的元素按特定顺序排列。孩子们不在他们自己的子列表中,他们都在同一个列表中。 所以,我试图创建一个Tree类,其中包含TreeNodes(类)使用Tree类中的List。 我如何跟踪父母/孩子/叶子?如果父母“父母1”,有两个孩子“孩子A”和“孩子B”,我如何将他们联系在一起?