I'm trying to render a dashboard using ResponsiveReactGridLayout
and my code in the functional component is as follows:
const Home = () => {
const [coins, setCoins] = useState(latestCoins);
const [coin, setCoin] = useState(curCoin);
const canvasRef = useRef(null);
useEffect(() => {
getCoins().then((data) => setCoins(data));
}, []);
return (
<ResponsiveReactGridLayout
onResize={(e) => console.log(e)}
className="layout"
layouts={layouts}
rowHeight={100}
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}
>
<div key="candlestick" className="home-card" ref={canvasRef}>
{console.log(canvasRef)}
//Trying to use canvasRef.current.width and height but getting an error: Property 'width' does not exist on type 'never'
<Candlestick coin={coin} width={600} height={400} />
</div>
</ResponsiveReactGridLayout>
);
};
My Candlestick component does return a ChartCanvas object from react-stockcharts
, which needs a width and height (without which it does not take up the entire space of the div)
How can I get the height and width from the div?
I've tried using the useRef()
hook, but it always seems to have current as null.
Could I get some help?
Property 'width' does not exist on type 'never'
This is actually a TypeScript error. It means that TypeScript doesn't know what the type of the .current
property is supposed to be. Therefore it doesn't know that .current
has properties .width
and .height
and it prevents you from accessing them. You need to tell TypeScript that this is a ref to a div
.
An HTMLDivElement
doesn't actually have .width
and .height
, but you can use .clientWidth
or .offsetWidth
instead.
const canvasRef = useRef<HTMLDivElement>(null);
I've tried using the useRef() hook, but it always seems to have current as null.
The ResponsiveReactGridLayout
component is setting its own refs on its children, so your ref={canvasRef}
gets overwritten.
The simplest way around this is to add another layer of nesting. The ResponsiveReactGridLayout
will set a ref on the outermost div
, but you can add another div
inside of it with a ref that you control. Make sure that it fills up the entire height.
Note that the .current
property might still be null
on the first render. You can use a default value, as suggested by @PushpikaWan, or you can delay rendering the chart until you have an actual width.
<ResponsiveReactGridLayout /*...props...*/ >
<div key="candlestick" className="box">
<div ref={canvasRef} style={{ width: "100%", height: "100%" }}>
{canvasRef.current ? (
<Candlestick
data={data}
width={canvasRef.current.clientWidth}
height={canvasRef.current.offsetHeight}
/>
) : null}
</div>
</div>
/*...other children...*/
</ResponsiveReactGridLayout>
I needed to add an explicit width
on the grid layout in order to get this to work. I'm not sure if you are doing this part already, but you can use the WidthProvider
as explained in the docs.
import { Responsive, WidthProvider } from 'react-grid-layout';
const ResponsiveReactGridLayout = WidthProvider(Responsive);