Brad
Brad

Reputation: 275

Get React.refs DOM node width after render and trigger a re-render only if width has value has changed

I'm attempting to get the width of a ref DOM element and set state to then use within the Component render. The problem comes because this width changes on user input and when I try setState within componentDidUpdate it starts an infinite loop and my browsers bombs.

I created a fiddle here http://jsbin.com/dizomohaso/1/edit?js,output (open the console for some information)

My thinking was;

Any help will be much appreciated, thanks for reading!

Brad.

Upvotes: 10

Views: 27909

Answers (1)

David
David

Reputation: 7456

var component = React.createClass({

  componentDidMount: function() {

    //Get initial width. Obviously, this will trigger a render,
    //but nothing will change, look wise.
    //But, if this is against personal taste then store this property 
    //in a different way
    //But it'll complicate your determineWidth logic a bit.        

    this.setState({
      elWidth: ReactDOM.findDOMNode(this.refs.the_input).getBoundingClientRect().width
    })
  },

  determineWidth: function() {

    var elWidth = ReactDOM.findDOMNode(this.refs.the_input).getBoundingClientRect().width

    if (this.state.elWidth && this.state.elWidth !== elWidth) {

      this.setState({
        elWidth: elWidth
      })

    }

  },

  render: function() {

    var styleProp = {}

    if (this.state.elWidth) {
      styleProp.style = { width: this.state.elWidth };
    }

    return (
      <input ref="the_input" onChange={this.determineWidth} {...styleProp} />
    )

  }

})

I like to use .getBoundingClientRect().width because depending on your browser, the element might have a fractional width, and that width will return without any rounding.

Upvotes: 22

Related Questions