Reputation: 29
I'm creating an array which will include the heights of some components in my app.
for doing that I had to get the elements and their heights.
I did it by this function:
getElement(method, elem){
switch (method){
case 'id':
return document.getElementById(elem);
case 'class':
return document.getElementsByClassName(elem);
case 'name':
return document.getElementsByName(elem);
case 'tagName':
return document.getElementsByTagName(elem);
default:
console.error('Incorrect use of getElement method')
}
}
and then I was inserting the heights of the elements by this function to my array:
heightsArr = [
this.getElement('id', 'home').clientHeight,
this.getElement('id', 'services').clientHeight
]
but then I'm getting an error:
TypeError: this.getElement(...) is null
I was trying to move the array to componentDidMount()
function, and then the error disappeared.
but then when I called the array, it returned me undefined
When it was in the componentDidMount()
I was trying to do console.log()
to the array, and it returns the array as expected with all of the heights
I'm trying to set set this array as NavBar
component by this code:
<NavBar heights={this.heightsArr}></NavBar>
but when I was inspecting the component by react addon for firefox, I saw that the props of the component are
{
heights: undefined
}
how can I fix it?
Now it's working and with the react inpector on the browser, I see that the heights are finnaly props of NavBar
.
I'm setting the props
as property of an object in an array, but when I'm logging to the console the value of that property I'm getting undefined.
My code that assigning the props
to the object is:
componentDidMount() {
this.sections.map(section => {
section.height = this.props.heights
})
}
Should I move this map
function to componentDidUpdate()
instead of componentDidMount()
?
Upvotes: 1
Views: 662
Reputation: 15688
React has access to the virtual DOM rather than the one you typically interact with using traditional dom selectors. To coordinate with React's lifecycle events, you should use React refs
instead.
Consider this sandbox: https://codesandbox.io/s/angry-wood-bp95g
Working code:
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
totalHeight: 0
};
this.home = React.createRef();
this.services = React.createRef();
}
componentDidMount() {
let allHeights = 0;
const refs = [this.home, this.services];
refs.forEach(ref => {
allHeights += ref.current.clientHeight;
});
this.setState({
totalHeight: allHeights
});
}
render() {
return (
<div>
<h4>Height: {this.state.totalHeight}</h4>
<div ref={this.home} style={{ height: "500px", background: "blue" }}>
Home Section
</div>
<div
ref={this.services}
style={{ height: "300px", background: "green" }}
>
Services
</div>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Refs give you access to the same element properties and methods you would with traditional selectors. In this case, we give each <div>
tag a ref
. Inside componentDidMount(), which is triggered right after the first render, we can tap into the height of these mounted elements using their .clientHeight
as expected.
We iterate over the refs
to get the total height and update our totalHeight
state-value. Similarly you can pass in that state to your Navbar component like:
<Navbar height={this.state.heights}/>
Upvotes: 2
Reputation: 6705
Also you can control element for not null or undefined on insert to array:
heightsArr = [
this.getElement('id', 'home') && this.getElement('id', 'home').clientHeight,
this.getElement('id', 'services') && this.getElement('id', 'services').clientHeight
]
Upvotes: 2