title: What is the react-way to handle state that will be impacted by refs
body: <p>So there have been a couple of times now where I have needed to set the state of a component based on properties that are computed at render. As a result, the component is rerendered sometimes. This isn't a huge concern, but it feels hacky and not the "react-way". So I am wondering if someone has a better solution. </p>
  
  <p>So the most recent example is an expandable text component. Similar to the review element on airbnb</p>
  
  <p><a href="https://i.stack.imgur.com/FTc0I.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/FTc0I.png" alt="enter image description here"></a></p>
  
  <p>This was fairly easy. But the last part was to detect whether there was any overflow and not display the "More" option if it is unnecessary. The solution I came up with was to check if the scrollHeight was greater than the clientHeight and set some state based on that. This is a simplified version of my solution. </p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>import React, { Component, PropTypes } from 'react';
  import classNames from 'classnames'
  
  function isOverflowed(element) {
    return element.scrollHeight &gt; element.clientHeight;
  }
  
  export default class ExpandableText extends Component {
    static propTypes = {
      content: PropTypes.string,
      maxHeight: PropTypes.number,
    };
  
    static defaultProps = {
      isOpen: false,
      maxHeight: 10,
    }
  
    constructor(props) {
      super(props);
  
      this.handleOpen = this.handleOpen.bind(this);
      this.handleClose = this.handleClose.bind(this);
  
      this.state = {
        isOpen: props.isOpen,
        isOverFlowed: true,
      };
    }
  
    componentDidMount() {
      if (!isOverflowed(this.refs.content)) {
        this.setState({ isOpen: true, isOverFlowed: false });
      }
    }
  
    handleOpen() {
      this.setState({ isOpen: true });
    }
  
    handleClose() {
      this.setState({ isOpen: false });
    }
  
    render() {
      const { content, maxHeight } = this.props;
      const { isOpen, isOverFlowed } = this.state;
      const contentClassName = classNames('expandable-text', {
        'expandable-text__content--closed': !isOpen,
        'expandable-text__content--open': isOpen,
      });
      const actionsClassName = classNames('expandable-text__actions', { hide: !isOverFlowed })
      return (
        &lt;div className="expandable-text"&gt;
          &lt;div
            ref="content"
            className={contentClassName}
            style={{
              maxHeight: isOpen ? 'none' : `${maxHeight}rem`,
            }}
          &gt;
     &lt;p&gt;{content}&lt;/p&gt;
          &lt;/div&gt;
          &lt;div className={actionsClassName}&gt;
            &lt;button onClick={isOpen ? this.handleClose : this.handleOpen}&gt;{isOpen ? 'Close': 'Open'}&lt;/button&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      );
    }
  }</code></pre>
  </div>
  </div>
  </p>
  
  <p>So there is a decent amount going on, but the important thing is in <code>componentDidMount</code> I am checking the overflow and then setting state (potentially) based on that. </p>
  
  <p>Now I realize that this could probably be accomplished by allowing a limit on number of characters instead of height, or some other solution. But if we assume the solution is similar to this, is there a more react-way to do this? (That doesn't require a rerender)</p>