Reputation: 35
I'm trying to build a navbar in React that has a child component Menu
that renders one of two different versions of the menu depending on the width on the div that the Menu is rendered inside. There is also a logo and company name that take up a relatively constant amount of width in the navbar and the div that holds the menu grows and shrinks to adjust for screen width and aspect ratio changes. Anyway, that div that grows and shrinks I gave an id="menu-section"
so that I could use document.getElementById("menu-section").offsetWidth;
to grab the available width and use that in the function that decided which version of the menu to render. The trouble is I get a TypeError: Cannot read property 'offsetWidth' of null
. Why would the document.getElementById("menu-section")
be failing to find the div and returning null?
function Menu(props) {
let availableWidthPx = document.getElementById("menu-section").offsetWidth;
if (availableWidthPx > 600) {
return expanded version;
}
return collapsed version
}
function Navbar(props) {
render(){
return (
<nav className="navbar">
...
<div id="menu-section">
<Menu />
</div>
</nav>
)
}
}
export default Navbar;
Upvotes: 2
Views: 14467
Reputation: 558
Because the DOM is not loaded yet. Here's how to fix it:
function Menu(props) {
React.useEffect(() => {
let availableWidthPx = document.getElementById("menu-section");
if (availableWidthPx) {
console.log(availableWidthPx.offsetWidth);
}
}, [])
return <div>Hello</div>;
}
Also, your Navbar
functional component needs just return
, not render
Upvotes: 8
Reputation: 175
You should also consider calling the Menu function after rendering, or define it in an afterRender()
block.
Upvotes: 0
Reputation: 944439
Because there isn't an element with that ID until all the rendering has finished and the result added to the DOM … but you are trying to call it from the render method.
Upvotes: 1