Skip to content

Instantly share code, notes, and snippets.

@trebor
Created April 2, 2022 18:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trebor/0adb495549f39e85d370ab8fe2f09de4 to your computer and use it in GitHub Desktop.
Save trebor/0adb495549f39e85d370ab8fe2f09de4 to your computer and use it in GitHub Desktop.
import React, { useRef, useEffect } from "react";
import { select } from "d3-selection";
import useComponentSize from "@rehooks/component-size";
const D3Svg = ({
data,
initialize = () => {},
margin = {
top: 0,
bottom: 0,
left: 0,
right: 0,
},
update = () => {},
}) => {
const svgRef = useRef();
const parentRef = useRef();
const { width, height } = useComponentSize(parentRef);
const hasSize =
typeof width !== "undefined" &&
typeof height !== "undefined" &&
width > 0 &&
height > 0;
useEffect(() => {
const chartRoot = select(svgRef.current)
.html("")
.append("g")
.classed("chart-root", true);
initialize(chartRoot);
}, [svgRef, initialize]);
useEffect(() => {
if (hasSize) {
const innerWidth = width - (margin.right + margin.left);
const innerHeight = height - (margin.bottom + margin.top);
const svg = select(svgRef.current)
.attr("width", width)
.attr("height", height);
const chartRoot = svg
.select(".chart-root")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
update(chartRoot, data, innerWidth, innerHeight, width, height, margin);
}
}, [data, hasSize, update, svgRef, width, height, margin]);
return (
<div
ref={parentRef}
style={{
display: "flex",
flex: "1 1 auto",
minWidth: "0px",
}}
>
<svg ref={svgRef} />
</div>
);
};
export default D3Svg;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment