'D3.js ResizeObserver rendering issue. Axis not removed after resizing
Been experimenting with ResizeObserver in D3, the issue is that when the axis re-renders it leaves the old render behind, leaving a 'trace' of the previous axis.
The code is just a blank chart template, I used ResizeObserver to get the size of the dimensions of the div from the contentRect. It does seem to resize however.
Better explained in an image:
My code:
const useResizeObserver = (ref) => {
const [dimensions, setDimensions] = useState(null);
useEffect(() => {
const observeTarget = ref.current;
const resizeObserver = new ResizeObserver(entries => {
entries.forEach(entry => {
setDimensions(entry.contentRect);
});
});
resizeObserver.observe(observeTarget);
return () => {
resizeObserver.unobserve(observeTarget);
};
}, [ref]);
return dimensions;
};
export default function BarChart() {
const [data, setData] = useState([10]);
const svgRef = useRef();
const wrapperRef = useRef();
const dimensions = useResizeObserver(wrapperRef);
useEffect(() => {
const margin = { top: 10, bottom: 10, right: 10, left: 10 };
const svg = select(svgRef.current);
if (!dimensions) return;
// xAxis
const xScale = scaleLinear()
.domain([0, 10])
.range([0, dimensions.width]);
const xAxisFormat = number => format('')(number);
const xAxis = axisBottom(xScale)
.ticks(10)
.tickFormat(xAxisFormat)
.tickPadding(10);
const xAxisG = svg.append('g')
.call(xAxis)
.attr('transform', `translate(0, ${height})`)
svg
.select('.xAxis')
.call(xAxis)
// yAxis
const yScale = scaleLinear()
.domain([0, 100])
.range([height, 0]);
const yAxisFormat = number => format('')(number);
const yAxis = axisLeft(yScale)
.ticks(10)
.tickFormat(yAxisFormat)
.tickPadding(10);
const yAxisG = svg.append('g')
.call(yAxis)
svg
.select('.xAxis')
.call(xAxis)
},[data, dimensions]);
return (
<React.Fragment>
<div ref={wrapperRef}>
<svg className="barChartSVG" ref={svgRef} width={width} height= {height} />
</div>
</React.Fragment>
);
}
Solution 1:[1]
Just add in the end of useEffect
next lines:
return () => {
svg.selectAll('*').remove()
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Vlad Novikov |