Home > Software design >  React get size of parent element within ResponsiveReactGridLayout
React get size of parent element within ResponsiveReactGridLayout

Time:09-26

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?

CodePudding user response:

You might get it as undefined with initial loading please use this optional statement there

canvasRef?.current?.width

If you have any default value u can use Nullish coalescing as well with the default value

canvasRef?.current?.width?? default_value

then it will be like below

 <Candlestick coin={coin} width={canvasRef?.current?.width?? default_width} height={canvasRef?.current?.height ?? default_Height} />

CodePudding user response:

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);

CodeSandbox Demo

  • Related