Javascript 在父级中的状态更改后,强制在React上重新渲染D3组件
我有两个react组件(在typescript中)。在第一个组件中,我有一些菜单Javascript 在父级中的状态更改后,强制在React上重新渲染D3组件,javascript,reactjs,typescript,d3.js,Javascript,Reactjs,Typescript,D3.js,我有两个react组件(在typescript中)。在第一个组件中,我有一些菜单 <Menu.Item name="graph" active={activeItem === "graph"} onClick={this.handleItemClick} /> <Menu.Item name="flow" active={activeItem === "flow"} onClick={
<Menu.Item
name="graph"
active={activeItem === "graph"}
onClick={this.handleItemClick}
/>
<Menu.Item
name="flow"
active={activeItem === "flow"}
onClick={this.handleItemClick}
/>
在render函数中,我将此决策作为属性传递给另一个react组件D3Core
回来之前,
var child = this.state.selection==="graph"? true : false ;
内部返回
<D3Core renderfull = {child} width={this.state.width} height={this.state.height} data={data} />
我面临的问题是,当我第一次加载文档时,它会显示图形,但如果我离开菜单并返回菜单,它只加载div而不是图形。我想我必须重新渲染图形,但是怎么做呢
我猜这是因为所有的组件都已经渲染,d3计算根本没有发生。我应该在渲染内部进行计算吗
我附上了几个截图。第一个屏幕截图显示首次加载页面时呈现的图形。第二个屏幕截图显示,当我离开graph菜单返回时,graph并不是只呈现div元素
编辑1:是我的d3代码吗
我认为问题在于当
renderfull
关闭并再次打开时,React会从文档中删除旧的div
,并添加一个新的,并且您的D3实例仍然连接到旧的(已删除的)div。但是,D3Core组件实例始终保持装载状态,因此,您不会得到一个新的组件didmount
回调
componentDidMount() {
const { width, height, data } = this.props;
const force = d3
.forceSimulation()
.nodes(data.nodes)
.force('charge', d3.forceManyBody().strength(-120))
.force('link', d3.forceLink(data.links).distance(50))
.force('center', d3.forceCenter(width / 2, height / 2));
const svg = d3
.select(this.ctrls.mountPoint)
.append('svg')
.attr('width', width)
.attr('height', height);
...
最干净的解决方案是将D3内容移动到
D3Core
的子组件(例如,假设该子组件名为D3Sub
),并且只有在renderfull
为true时才具有D3Core
的render
方法返回
。然后,当renderfull
被关闭并再次打开时,D3Sub
实例将被销毁,并将创建一个新的D3Sub
实例,新实例将得到一个componentDidMount
回调。您在div
中还有SVG吗,当组件被隐藏时,您是否会破坏SVG?@rioV8否我不会破坏它。我在帖子中添加了我的代码。var child=this.state.selection==“graph”
足够了,表达式是布尔表达式,这解决了问题。但是,正如您所说的“React从文档中删除旧div并添加新div”,componentDidMount回调不应该再次触发吗?给定的D3Core
组件实例上的componentDidMount
回调只在该实例完全初始化后调用一次。在此之后,实例可能会多次重新渲染(导致添加和/或删除DOM元素和子组件),每次您都会得到一个componentDidUpdate
,而不是componentDidMount
。原则上,您可以编写componentdiddupdate
来检查renderfull
是否从false变为true,如果是,则初始化另一个D3实例,但是使用子组件可以避免在componentDidMount
和componentdiddupdate
之间重复代码。是否会在componentDidMount之前调用component did update?组件的第一次呈现调用componentDidMount
,而不是componentdiddupdate
;看见如果您的问题是关于父组件的componentdiddupdate
与父组件重新渲染时刚刚创建的子组件的componentDidMount
的顺序,我相信子组件的componentDidMount
是第一位的,但您可以试试看。
componentDidMount() {
const { width, height, data } = this.props;
const force = d3
.forceSimulation()
.nodes(data.nodes)
.force('charge', d3.forceManyBody().strength(-120))
.force('link', d3.forceLink(data.links).distance(50))
.force('center', d3.forceCenter(width / 2, height / 2));
const svg = d3
.select(this.ctrls.mountPoint)
.append('svg')
.attr('width', width)
.attr('height', height);
...
componentDidMount() {
const { width, height, data } = this.props;
const force = d3
.forceSimulation()
.nodes(data.nodes)
.force('charge', d3.forceManyBody().strength(-120))
.force('link', d3.forceLink(data.links).distance(50))
.force('center', d3.forceCenter(width / 2, height / 2));
const svg = d3
.select(this.ctrls.mountPoint)
.append('svg')
.attr('width', width)
.attr('height', height);
...