1

I found the code snippet from this answer for tracking page size to be useful. I want to switch window.innerHeight with $("#list_container").height:

constructor(props) {
  super(props);
  this.state = { width: 0, height: 0 };
  this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
}

componentDidMount() {
  this.updateWindowDimensions();
  window.addEventListener('resize', this.updateWindowDimensions);
}

componentWillUnmount() {
  window.removeEventListener('resize', this.updateWindowDimensions);
}

updateWindowDimensions() {
  // !!! This works:
  this.setState({ width: window.innerWidth, height: window.innerHeight });
  // !!! This doesn't work:
  this.setState({ width: $("#list_container").width(), height: $("#list_container").height() });
}

Edit: Updated to .width() and .height(), had tried both but neither is working for me.

List container is defined in the same module as the outer div:

render() {
  return (
    <div id="list_container">
      <ListGroup>
        <VirtualList
            width='100%'
            height={this.state.height}
            itemCount={this.state.networks.length}
            itemSize={50}
            renderItem={({index, style}) =>
              <ListGroupItem
                onClick={() => this.updateNetwork(this.state.networks[index].ssid, this.state.networks[index].security)}
              action>
              {this.state.networks[index].ssid}
            </ListGroupItem>
          }
        />
      </ListGroup>
      <Modal/>
      // ...

Note:

If I do:

<p>{this.state.height}</p>

It isn't 0 just empty, with the example that doesn't work.

Philip Kirkbride
  • 21,381
  • 38
  • 125
  • 225

3 Answers3

1

If it's jQuery you're using, width() and height() are functions, not properties. Try:

this.setState({ width: $("#list_container").width(), height: $("#list_container").height() });
Miguel Calderón
  • 3,001
  • 1
  • 16
  • 18
1

you need to use refs since the js might be running before the component renders to the dom.

React documentation on refs

render() {
  return (
    <div id="list_container" ref={ el => this.componentName = el }>
      // ...

to reference this dom node in this component you just have to call this.componentName

updateWindowDimensions = () => {
  $(this.componentName).height()  // returns height
}
Eric Hasselbring
  • 1,374
  • 1
  • 10
  • 18
  • 1
    Inside `componentDidMount`, all of the DOM nodes should be mounted on the screen already ([see docs](https://reactjs.org/docs/react-component.html#componentdidmount)). I do agree with you that `refs` are the recommended way to break out of the React abstraction. – Anthony N Feb 22 '18 at 16:30
  • Thanks but it returns 0 for me – Philip Kirkbride Feb 22 '18 at 16:31
  • true, it was not the best example... it would be necessary for `updateWindowDimensions` – Eric Hasselbring Feb 22 '18 at 16:31
  • wait let me try something else I didn't have it in `componentDidMount()` – Philip Kirkbride Feb 22 '18 at 16:32
  • does your list container have height? it may show 0 if its children are absolutely positioned, in which case you would have to look into a clearfix solution to get the proper height – Eric Hasselbring Feb 22 '18 at 16:45
1

To expand on Erics answer using refs, to pull it off without jQuery, you can use getBoundingClientRect:

const listRect = document.getElementById('list_container').getBoundingClientRect();

or if using the ref from Erics answer:

const listRect = this.componentName.getBoundingClientRect();

followed by

this.setState({ 
  width: listRect.width, 
  height: listRect.height
});

I would suggest this page for some good examples of life without jQuery.

Also, I would strongly suggest debouncing the resize handler.

Ted
  • 14,757
  • 2
  • 41
  • 58
  • sorry, not sure where to put it. Trying in `componentDidMount()` but it seems to stay 0. – Philip Kirkbride Feb 22 '18 at 16:41
  • @PhilipKirkbride, hard to say without seeing your full code, but that would seem to indicate that the list container contents haven't rendered yet. Is that a separate component or coming in a callback? – Ted Feb 22 '18 at 16:44
  • I added a bit to the question. I think I need to use this but run after rendering like you say. – Philip Kirkbride Feb 22 '18 at 16:52