Reputation: 21
I am not sure how can I fix this so that upon screen resize a new width is set. Currently it is failing resize: TypeError: el.getBoundingClientRect is not a function It calculates the correct width on load but brakes on resize
import React, { useEffect, useCallback, useState, useLayoutEffect } from 'react'
import charts from 'charts'
const Charts = props => {
const
chartRenderers = {
line: charts.d3_line(),
horizontalBar: charts.d3_horizontal_bar(),
tables: charts.d3_table()
},
// https://reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node
useWidth = () => {
const
[width, setWidth] = useState(null),
ref = useCallback(el => {
console.log(el)
if (el !== null) {
setWidth(el.getBoundingClientRect().width);
}
}, []);
useLayoutEffect(() => {
window.addEventListener('resize', ref, false);
return () => {
window.removeEventListener('resize', ref);
}
}, [ref])
return [width, ref];
},
{ component, siteData } = props,
[width, ref] = useWidth();
useEffect(
() => {
const parsedData = component.type === "tables" ? JSON.parse(siteData) : siteData
chartRenderers[component.type].renderChart(
parsedData,
charts.d3.select(`#${component.id}`),
width,
component.height,
component.options
)
}
)
return <div id={component.id} key={component.id} ref={ref}/>
}
export default Charts
Upvotes: 1
Views: 6614
Reputation: 174
It looks like you are not calling the function anywhere when the window resizes. Try changing the useWidth
implementation to:
import { useState, useCallback } from 'react';
function useWidth(elementRef) {
const [width, setWidth] = useState(null);
const updateWidth = useCallback(() => {
if(elementRef && elementRef.current) {
const { width } = elementRef.current.getBoundingClientRect();
setWidth(width);
}
}, [elementRef]);
useEffect(() => {
updateWidth();
window.addEventListener('resize', updateWidth);
return () => {
window.removeEventListener('resize', updateWidth);
}
}, [updateWidth])
return [width]
}
Usage
import React, { useRef } from 'react';
const Charts = props => {
const ref = useRef(null);
// rest of code
const [width] = useWidth(ref);
// do wherever you want with width
return (
<div ref={ref}/>
)
}
Upvotes: 7