4

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?

Linda Paiste
  • 38,446
  • 6
  • 64
  • 102
  • Please add UseRef() code as well with the description. Most probably u might use it out side of react scope of updating values – PushpikaWan Sep 25 '21 at 15:42

2 Answers2

2

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

Linda Paiste
  • 38,446
  • 6
  • 64
  • 102
0

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} />
PushpikaWan
  • 2,437
  • 3
  • 14
  • 23
  • Unfortunately this did not work. Still saw the same error of ```Property 'width' does not exist on type 'never'.``` – Shubhankar Agrawal Sep 25 '21 at 16:10
  • @ShubhankarAgrawal that's a TypeScript error. You need to use `const canvasRef = useRef(null);` – Linda Paiste Sep 25 '21 at 16:14
  • @LindaPaiste, thanks for correcting me on that, but I still see canvasRef.current is always null. – Shubhankar Agrawal Sep 25 '21 at 16:21
  • Is it *always* `null`, or always `null` on just the first render? I think it will be `null` at first and then get a value. But tbh you aren't making use of the `onResize` function which is probably the better method. I might go update my answer. – Linda Paiste Sep 25 '21 at 16:22
  • @LindaPaiste, it's always null no matter how many times I refresh. Apologies I'm new to ReactJS – Shubhankar Agrawal Sep 25 '21 at 16:53
  • @ShubhankarAgrawal I think what's happening is that the `react-grid-layout` package is setting its own ref on the child div and overriding your ref, but I have to look into it more. – Linda Paiste Sep 25 '21 at 17:21