Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;

  • Component Mounts, setState: refs.element.clientWidth

  • User inputs data, triggers render

  • shouldComponentUpdate returns true only if new.state is not equal to old.state. My problem is, I'm not sure where makes sense to update this state?

Any help will be much appreciated, thanks for reading!

Brad.

like image 578
Brad Avatar asked Feb 18 '16 22:02

Brad


1 Answers

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.

like image 120
David Avatar answered Oct 21 '22 07:10

David