代码之家  ›  专栏  ›  技术社区  ›  Rohullah Rajaee Rad

ReactJS:调用子级来自另一个子组件的方法?

  •  0
  • Rohullah Rajaee Rad  · 技术社区  · 5 年前

    我使用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;
    

    2) 历史记录:

    import React, { Component } from "react";
    
    import {Modal } from "antd";
    
    class History extends Component {
      state = {
        modalVisible: false,
        tableData: [{}]
      };
    
      //i need call this method //
      modalHistoryShow = nodeId => {
        axios.get("api/tag-values/get-history/" + nodeId).then(response => {
          this.setState({ tableData: response.data });
          console.log(this.state.tableData);
        });
        this.setState({ modalVisible: true });
      };
    
    render(){
        return (
          <Modal
            visible={this.state.modalVisible}
            name="modalHistory"
            footer={[null]}
            width={"1000px"}
          >
          </Modal>
        );
      }
    }
    
    export default History;
    

    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;
    
    0 回复  |  直到 5 年前
        1
  •  0
  •   Striker    5 年前

    也许我的答案是最通用的,但我认为最好的选择是下表:-

    1. 将node Id传递给history组件,并在history组件中使用useffect钩子,并使用nodeId作为依赖项,以便每当节点Id在useffect中更改时,都将执行代码。e、 克-
    useEffect(()=>{
         // your logic to execute goes here
         },[nodeId])
    
    1. 创建一个自定义钩子,将历史组件中的代码提取出来,然后可以从任何地方调用相同的钩子,这样就可以使代码可重用。