ReactJS:从另一个子组件调用子方法?

ReactJS:从另一个子组件调用子方法?,reactjs,d3.js,Reactjs,D3.js,我使用ReactJS 16.12,有三个组件。1) 家长2)历史记录3)SvgViewer。我想从SvgViewer函数组件(另一个子组件)调用属于历史组件(子组件)的函数。 谢谢你的解决方案 这是我的代码: 1) 父组件: import React, { PureComponent } from "react"; import History from "./history"; import SvgViewer from "./svg-viewer"; class UnitMonitor e

我使用ReactJS 16.12,有三个组件。1) 家长2)历史记录3)SvgViewer。我想从SvgViewer函数组件(另一个子组件)调用属于历史组件(子组件)的函数。 谢谢你的解决方案

这是我的代码:

1) 父组件:

import React, { PureComponent } from "react";
import History from "./history";
import SvgViewer from "./svg-viewer";

class UnitMonitor extends PureComponent {
  constructor() {
    super();
    this.History = React.createRef();
  }

  render() {
    return (
      <Row type="flex" className="">
        <Col span={25}>
          <History ref={this.History} />
          <SvgViewer
            svgFilePath={this.state.svgFilePath}
            nodesData={this.state.nodes}
          />
        </Col>
      </Row>
    );
  }
}
export default UnitMonitor;
import React,{PureComponent}来自“React”;
从“/History”导入历史记录;
从“/svg查看器”导入SvgViewer;
类UnitMonitor扩展了PureComponent{
构造函数(){
超级();
this.History=React.createRef();
}
render(){
返回(
);
}
}
导出默认单元监视器;
2) 历史:

import React,{Component}来自“React”;
从“antd”导入{Modal};
类历史扩展组件{
状态={
modalVisible:错误,
tableData:[{}]
};
//我需要调用这个方法//
modalHistoryShow=nodeId=>{
get(“api/tagvalues/get history/”+nodeId)。然后(response=>{
this.setState({tableData:response.data});
log(this.state.tableData);
});
this.setState({modalVisible:true});
};
render(){
返回(
);
}
}
导出默认历史记录;
3) SvgViewer:

import React, { useEffect, useState } from "react";
import * as d3 from "d3";

const SvgViewer = ({ nodesData, svgFilePath }) => {
  const [svgContainer, setSvgContainer] = useState(undefined);

  const showNodesOnSvg = nodes => {
    //this.setState({ objectLoading: false });
    //let nodesData = UnitMonitor.state.nodes;
    let svgDoc = svgContainer.contentDocument;
    let gTags = svgDoc.querySelectorAll("svg > g");
    let container = null;
    if (gTags.length > 1) container = svgDoc.querySelector("g:nth-of-type(2)");
    else container = svgDoc.querySelector("g:nth-of-type(1)");
    let node = d3.select(container);
    nodesData.forEach(nodeData => {
      node
        .append("text")
        .attr("id", "node" + nodeData["id"])
        .attr("fill", "white")
        .attr("text-anchor", "middle")
        .attr("x", nodeData["positionX"])
        .attr("y", nodeData["positionY"])
        .attr("class", "clickable-node")
        .style("font-size", "8px")
        .style("position", "absolute")
        .style("cursor", "pointer")
        .style("display", "inline-block")
        .on("click", function() {
          clickHandler(nodeData["id"]);
        })
        .text("N/A" + " " + nodeData["symbol"]);
      let nodeCreated = d3.select(
        svgDoc.getElementById("node" + nodeData["id"])
      );
      nodeCreated
        .append("title")
        .attr("id", "title" + nodeData["id"])
        .text(" " + nodeData["tagCode"]);
    });
  };
  const clickHandler = nodeID => {
     History.ModalHistoryShow(nodeID); // i need call ModalHistoryShow() this way
  };
  useEffect(() => {
    const svg = document.querySelector("#svgobject");
    setSvgContainer(svg);
    svg.onload = () => {
      if (nodesData != null) {
        showNodesOnSvg();
      }
    };
  });

  return (
    <div className="unit-schema-container1" key={svgFilePath}>
      <object id="svgobject" type="image/svg+xml" data={svgFilePath}></object>
    </div>
  );
};
export default SvgViewer;
import React,{useffect,useState}来自“React”;
从“d3”导入*作为d3;
const SvgViewer=({nodesData,svgFilePath})=>{
const[svgContainer,setSvgContainer]=使用状态(未定义);
const showNodesOnSvg=节点=>{
//this.setState({objectload:false});
//让nodesData=UnitMonitor.state.nodes;
设svgDoc=svgContainer.contentDocument;
让gTags=svgDoc.queryselectoral(“svg>g”);
让container=null;
如果(gTags.length>1)container=svgDoc.querySelector(“g:n类型(2)”);
else container=svgDoc.querySelector(“g:nth类型(1)”;
让节点=d3.选择(容器);
nodesData.forEach(nodeData=>{
节点
.append(“文本”)
.attr(“id”、“节点”+节点数据[“id”])
.attr(“填充”、“白色”)
.attr(“文本锚定”、“中间”)
.attr(“x”,节点数据[“位置x”])
.attr(“y”,nodeData[“positionY”])
.attr(“类”、“可单击节点”)
.style(“字体大小”,“8px”)
.style(“位置”、“绝对”)
.style(“光标”、“指针”)
.style(“显示”、“内联块”)
.on(“单击”,函数(){
clickHandler(nodeData[“id”]);
})
.text(“不适用”+“”+节点数据[“符号”);
让nodeCreated=d3.select(
svgDoc.getElementById(“节点”+nodeData[“id”])
);
不屑
.附加(“标题”)
.attr(“id”,“title”+节点数据[“id”])
.text(“+nodeData[“标记码]);
});
};
const clickHandler=nodeID=>{
ModalHistoryShow(nodeID);//我需要这样调用ModalHistoryShow()
};
useffect(()=>{
const svg=document.querySelector(“svgobject”);
设置VGC容器(svg);
svg.onload=()=>{
if(nodesData!=null){
showNodesOnSvg();
}
};
});
返回(
);
};
导出默认SvgViewer;

也许我的答案是最一般的,但我认为最好的选择是以下两件事之一:-

  • 将nodeId传递给history组件,并在history组件中使用useEffect钩子,并将nodeId用作依赖项,以便每次节点Id更改时,都会执行useEffect中的代码。e、 g-
  • 创建一个自定义钩子,将您的代码从历史组件中提取出来,然后可以从您的代码的任何地方调用相同的钩子,从而使您的代码可重用

  • 您可以将
    nodeId
    传递到
    History
    组件,并在更新
    nodeId
    时从该组件调用该函数。@Superblar,我是react.js中的新手。请给我一个示例代码
    import React, { useEffect, useState } from "react";
    import * as d3 from "d3";
    
    const SvgViewer = ({ nodesData, svgFilePath }) => {
      const [svgContainer, setSvgContainer] = useState(undefined);
    
      const showNodesOnSvg = nodes => {
        //this.setState({ objectLoading: false });
        //let nodesData = UnitMonitor.state.nodes;
        let svgDoc = svgContainer.contentDocument;
        let gTags = svgDoc.querySelectorAll("svg > g");
        let container = null;
        if (gTags.length > 1) container = svgDoc.querySelector("g:nth-of-type(2)");
        else container = svgDoc.querySelector("g:nth-of-type(1)");
        let node = d3.select(container);
        nodesData.forEach(nodeData => {
          node
            .append("text")
            .attr("id", "node" + nodeData["id"])
            .attr("fill", "white")
            .attr("text-anchor", "middle")
            .attr("x", nodeData["positionX"])
            .attr("y", nodeData["positionY"])
            .attr("class", "clickable-node")
            .style("font-size", "8px")
            .style("position", "absolute")
            .style("cursor", "pointer")
            .style("display", "inline-block")
            .on("click", function() {
              clickHandler(nodeData["id"]);
            })
            .text("N/A" + " " + nodeData["symbol"]);
          let nodeCreated = d3.select(
            svgDoc.getElementById("node" + nodeData["id"])
          );
          nodeCreated
            .append("title")
            .attr("id", "title" + nodeData["id"])
            .text(" " + nodeData["tagCode"]);
        });
      };
      const clickHandler = nodeID => {
         History.ModalHistoryShow(nodeID); // i need call ModalHistoryShow() this way
      };
      useEffect(() => {
        const svg = document.querySelector("#svgobject");
        setSvgContainer(svg);
        svg.onload = () => {
          if (nodesData != null) {
            showNodesOnSvg();
          }
        };
      });
    
      return (
        <div className="unit-schema-container1" key={svgFilePath}>
          <object id="svgobject" type="image/svg+xml" data={svgFilePath}></object>
        </div>
      );
    };
    export default SvgViewer;
    
    useEffect(()=>{
         // your logic to execute goes here
         },[nodeId])