我试图使用react组件递归地构造一个树的一个SVG(一个json-object)。 每个节点(树的节点)组件返回其他节点(和边缘),直到不再有子节点。树在我的屏幕上呈现完美。
现在我想使用一个函数计算所有leafe-nodes,我通过props向所有节点传递。当节点没有子节点时,它会在其构造函数中调用该函数。使用此函数,我想使用this.setState增加我的主要组件的this.state.countLeafs。我的树中有leafe节点经常调用该函数(我用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;
我有什么基础吗?
谢谢
答案 0 :(得分:0)
你确定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组件中的componentDidMount
constructor(props){
super(props);
}
componentDidMount() {
if(!this.props.k){
this.props.incLeafs();
}
}
答案 1 :(得分:0)
您的方法this.incLeafs
未绑定到父组件。因此,当它运行时,this
在子节点调用方法时并不代表GraphicController
。
要么
A)改变你将父类的方法编写成箭头函数的方式,如下所示:incLeafs = () => {...};
B)在某些时候用this.incLeafsHandler = this.incLeafs.bind(this)
之类的方法手动绑定方法方法,然后将this.incLeafsHandler
作为incLeaf回调传递给SpecNode。 ((我非常不喜欢这个解决方案,但这只是我的偏好。)
C),将其作为道具中的箭头功能传递下来(如<SpecNode ... incLeafs={() => this.incLeafs()} />
)
箭头函数始终保留this
,就像宣布箭头函数时一样。 (选项A和C)
正常函数将根据它们被调用的位置更改this
,除非您使用原始方法的绑定副本。 (选项B)