Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: To know size of the element before it gets rendered

Tags:

reactjs

Suppose that a component needs to know its size before it renders. With my knowledge I can do this: render the component, in componentDidMount get the DOM node and extract size out of it, update state with that size, and then render again (lets not make it complicated with event listeners I'd attach to window's resize event, lets assume that window doesn't resize) It works but seems dirty, the first render is just waste of resources, I wanna know the size of the element (or its container) before it's rendered, I know most of the time the element itself declares the size, but there are some situations when parent element declares the size and my case is one of those situations. So to sum it up, is there any way to access parent element of a react component before it gets rendered (in componentWillMount)?

P.S. I know react-dimmensions, but I'd like a simpler solution that doesn't need external plugins. I just wanna know if it's possible to access parent node in componentWillMount in react or not.

like image 603
Sassan Avatar asked Jun 18 '16 06:06

Sassan


People also ask

How do you determine the size of an element in React?

To get the height of an element with React, we can assign a ref to the element we want to get the height for. Then we can use the clientHeight property to get the height. We call the useRef hook and assign the returned ref to elementRef . Then we set elementRef as the value of the ref prop of the div.

How do you find the width of a container in React?

To get the width of an element in a React component, we can assign a ref to the element we want to get the width of. Then we can use the offsetWidth property to get the width. to add the ref with the useRef hook. Then we pass ref as the value of the ref prop to assign the ref to the div.

How wait for data before rendering React?

React does not wait to render.There is no way to make it wait. All is not lost, though. There's an easy fix. Components that render async data need to be prepared to render an empty state, at least once.


1 Answers

The answer is no, but please read for ideas how to cope.

If the DOM element doesn't exist, you can't find its dimensions. The DOM element doesn't exist until the first render for each component has been done. You can't know anything about this DOM element or its parent until the component's componentDidMount() is called.

Note also the order that components are rendered. On the initial rendering of a tree/chain of components, the child's componentDidMount() will be called before the parent's componentDidMount() ! Here's a snapshot of logs from a nested menu tree:

(MenuItemSubmenu:handleRefSet)          appMenu:2.2.5.4   handleRefSet()
(MenuItemSubmenu:componentDidMount)     appMenu:2.2.5.4   componentDidMount()
(MenuPane:handleRefSet)                 appMenu:2.2.5   handleRefSet()
(MenuPane:componentDidMount)            appMenu:2.2.5   componentDidMount()
(MenuItemSubmenu:handleRefSet)          appMenu:2.2.5   handleRefSet()
(MenuItemSubmenu:componentDidMount)     appMenu:2.2.5   componentDidMount()
(MenuPane:handleRefSet)                 appMenu:2.2   handleRefSet()
(MenuPane:componentDidMount)            appMenu:2.2   componentDidMount()
(MenuItemSubmenu:handleRefSet)          appMenu:2.2   handleRefSet()
(MenuItemSubmenu:componentDidMount)     appMenu:2.2   componentDidMount()

componentDidMount() for child item 2.2.5.4 is called before that for its parent item 2.2.5. From that we can see that the parent component can't know its own DOM element until all processing for the child has completed. Um, wow!

However, pursuing your question, I added some logging to a component's componentDidMount() method. I logged this.refToOurDom.parentElement and found that it was defined and looked good!

(MenuItemSubmenu:handleRefSet)  appMenu:2.2.5.4   parent dims:  height 76   width 127

So the answer to your question is, no, your DOM element doesn't exist yet in componentWillMount() and the parent doesn't exist either on initial render. You must wait until componentDidMount() is called before finding out any component's dimensions.

But please note the trick that react-dimensions uses. Perhaps that will give you ideas how to structure your code.

In its render() method react-dimensions may not render the enclosed component! On the initial render it only renders the containing <div>. Only after its componentDidMount() is called and it finds out the parent's dimensions, only then will the enclosed component be rendered, and now supplying the parent's dimensions.

So another answer is just don't render your component's contents until you know the dimensions of the parent. Using react-dimensions makes that easy, because you aren't even rendered until the dimensions are known. But you could also do the same sort of thing, getting the reference in your componentDidMount() and grabbing dimensions, and simply putting an if(){} around rendering the real contents of your component until you know the dimensions. (You'll need at least an outer <div> to get your own ref)

like image 177
Shenme Avatar answered Sep 19 '22 00:09

Shenme