Ganesh
Ganesh

Reputation: 1919

Not getting tree with expected link style in ReactJS using D3

I'm pretty new to D3.js library. I've been trying to implement it in React JS project.

I'm just using d3 functions for calculations and rendering part will be done by React JS.

I successfully created a tree but I'm getting links with weird style (Not as expected)

This is what I expected (As per D3 Documentation) Expected Result

But I got the below tree :( enter image description here

Also I can't able to collapse or expand...

You can find the code below.

componentDidMount() {
        const width = 800, height = 800;

        const tree = d3.tree().size([height, width - 160]);
        const stratify = d3.stratify().id((d) => {
            return d.name;
        }).parentId((d) => {
            return d.parent;
        });
        const root = stratify(this.state.data)
            .sort((a, b) => {
                return (a.height - b.height) || a.id.localeCompare(b.id);
            });

        this.setState({ paths: tree(root).links() });
        this.setState({ nodes: root.descendants() })
    }

    render() {
        let paths = this.state.paths && this.state.paths.map(item => {
            let d = d3
                .linkHorizontal()
                .x((d) => {
                    return d.y;
                })
                .y((d) => {
                    return d.x;
                });
            return <path className='link' d={d(item)} />
        })
        let nodes = this.state.nodes && this.state.nodes.map((node, i) => {
            return <g key={node.id} className={"node" + node.children ? " node--internal" : " node--leaf"}
                transform={`translate(${node.y}, ${node.x})`}>
                <circle r="10" style={{ 'fill': node.children ? 'lightsteelblue' : 'black' }} />
                <text y="0" dy="0" textAnchor="middle"
                    style={{ 'fillOpacity': 1 }}>{node.name}</text>
            </g>
        })
        return (
            <svg className="tree-chart-basic" ref={(r) => this.chartRf = r} style={{ width: '800px', height: '800px' }}>
                <g transform='translate(20,20)'>
                    {nodes}
                    {paths}
                </g>
            </svg>
        );
    }

this.state.data will be having the array as follows

    [
        { "name": "ProjectA", "parent": "" },
        { "name": "ApplicationA", "parent": "ProjectA" },
        { "name": "EnvironmentB", "parent": "ProjectA" },

        { "name": "TierC", "parent": "ApplicationA" },
        { "name": "TierD", "parent": "ApplicationA" },
        { "name": "TierE", "parent": "ApplicationA" },

        { "name": "ServiceF", "parent": "EnvironmentB" },

        { "name": "ContainerG", "parent": "EnvironmentB" },
        { "name": "ContainerH", "parent": "TierE" },
        { "name": "ContainerH", "parent": "TierE" },
        { "name": "ContainerH", "parent": "TierE" },
        { "name": "ContainerH", "parent": "TierE" },
        { "name": "ContainerH", "parent": "TierE" },
        { "name": "ContainerH", "parent": "TierE" }
    ]
  1. How can I get the expected Tree in my code?
  2. How can I get collapse/expand functionality?

Please tell me what I'm doing wrong. Thanks for the time. (:

Upvotes: 3

Views: 2197

Answers (2)

Martin
Martin

Reputation: 6162

I had the same issue when using react-tree-graph which uses d3 under the hood. Luckily you can add custom classes to customize everything. I use css-modules so I had to escape the global classnames.

import { Tree } from 'react-tree-graph';
import style from './tree.module.scss';
// ...
<Tree svgProps={{ className: style.acmeProductTree }} />
// tree.module.scss
svg.acmeProductTree path:global(.link) {
  fill: none;
  stroke: #2593b8;
  stroke-width: 1.5px;
}

As I found out just now you can alternatively apply a custom class directly to the path element:

<Tree pathProps={{ className: style.acmeProductTreeLink }} />
.acmeProductTreeLink {
  fill: none;
  stroke: #2593b8;
  stroke-width: 1.5px;
}

Upvotes: 0

Ganesh
Ganesh

Reputation: 1919

I finally got the solution to my answer.

I need to specify the style to <path> tag as follows.

<path
fill="none" 
stroke="#97a6ff" 
strokeWidth="2px" 
/>

Upvotes: 2

Related Questions