首页 > 解决方案 > ReactJS:从另一个子组件调用子方法?

问题描述

我使用 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)SVG查看器:

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;

标签: reactjsd3.js

解决方案


可能是我的回答是最通用的,但我认为我认为最好的选择是以下两件事之一:-

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

推荐阅读