简体   繁体   中英

d3+react.js on click of d3 tree node text this.props.history.push gives error "Cannot read properties of undefined (reading 'props')"

With the help of d3 and react.js, I am able to create d3 hierarchy tree

在此处输入图像描述

What I want to achieve is, On click of each node text (eg John, Luke, ...) it should route to detail page of each clicked text.

nodes
    .append("text")
    .attr("font-size", "17px")
    .attr("text-anchor", "start")
    .text(function (d) {
        return `${d.data.name}`
    })
    .on("click", function (event, d) {
        this.props.history.push(`/detail/${d.id}`);
});

constructor

constructor(props) {
    super(props);
    console.log(this.props)                  // there is history in props
    this.state = {
      isClicked: ""
      };
    this.geGraph = this.getGraph.bind(this);  // function where graph code presents

after clicking the node text. I getting error.

Uncaught TypeError: Cannot read properties of undefined (reading 'history')

Also when I debug on line this.props.history.push , there is no props in this .

Tried to follow this How to use React Router with d3.js Graphs to redirect to another screen . still got the same issue. and when i try to go for arrow function

.on("click", (event, d) => this.props.history.push(`/detail/${d.id}`))

it gives issue for props this time Uncaught TypeError: Cannot read properties of undefined (reading 'props')

I have added history in <Route history={createBrowserHistory()}/> as well import { createBrowserHistory } from "history"; . and did export default withRouter(MyGraph) imported from import { withRouter } from 'react-router-dom'; .

I m using router version "react-router-dom": "^4.3.1" and class based components with typescript.

How do I resolve this issue.

Thanks in advance!

Your are using this on different scope , its scope is functional now, its better to define a function for click inside component and call it on click event.

Or you can store this value in another variable inside nodes creation scope and use it from that.

According to the javascript DOM API documentation , the reference to this will be the DOM element you will click on.

nodes
    .append("text")
    .attr("font-size", "17px")
    .attr("text-anchor", "start")
    .text(function (d) {
        return `${d.data.name}`
    })
    .on("click", function (event, d) {
        // try console.log here
        console.log(this);   // <--- most likely be a DOM element you clicked
        this.props.history.push(`/detail/${d.id}`); // <--- therefore this.props does not exist
});

Solution 1

use either Javascript arrow function :

.on("click", (event, d) => {
        console.log(this);   // <--- this should refer to the parent object
        this.props.history.push(`/detail/${d.id}`);
});

Solution 2

or bind the click event handler in the constructor with this

constructor(props) {
    super(props);
    console.log(this.props)                  
    this.state = {
      isClicked: ""
      };
    this.geGraph = this.getGraph.bind(this);
    this.nodeClickHandler = this.nodeClickHandler.bind(this);
}

function nodeClickHandler (event, d) {
    this.props.history.push(`/detail/${d.id}`);
}
nodes
    .append("text")
    .attr("font-size", "17px")
    .attr("text-anchor", "start")
    .text(function (d) {
        return `${d.data.name}`
    })
    .on("click", this.nodeClickHandler);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM