score:2

Accepted answer

this is a tricky problem more related to your usage of the styled-components library with react than your react code itself. in the render of your textarea1 you are creating a styledtextarea with a style prop passed in. unfortunately this prop is ignored by components created with styled-components.

when using styled-components with react you are supposed to pull your props out and apply them to your css, as shown in this code-pen:

const styled = styled.default;

const button = styled.button`
  background: red;
  border-radius: 8px;
  color: white;
  height: ${props => props.small ? 40 : 60}px;
  width: ${props => props.small ? 60 : 120}px;
`;

class application extends react.component {
  render() {
    return (
      <div>
        <button small>click me</button>
        <button large>click me</button>
      </div>
    )
  }
}

reactdom.render(<application />, document.getelementbyid('content'));

to fix your problem you will have to pull your style.height prop out in your styledtextarea and reset your height to '' at the end of textarea2.onchange. here is your code with these changes. note that this breaks the resizing done in textarea1:

const styled = styled.default;

const styledtextarea = styled.textarea`
  display: block;
  font-family: pt sans;
  font-size: 20px;
  line-height: 40px;
  min-height: 120px;
  overflow: hidden;
  padding: 0 7px;
  margin: 0 0 30px;
  resize: none;
  width: 500px;
  // one update here
  height: ${props => (props.style && props.style.height) ? props.style.height + 'px' : '0px'};
`;

const label = styled.span`
  color: ${props => props.green ? '#00bb00' : 'red'};
  font-size: 1.5em;
`;

const app = () => {
  return(
    <div>
      <label green>✅ textarea1 - working </label>
      <textarea1 />
      <label>❌ textarea2 - not working </label>
      <textarea2 />
    </div>
  )
}

class textarea1 extends react.component {

    constructor(props) {
        super(props);
        this.state = {
          value: 'lorem ipsum dolor sit amet, consectetur adipisicing elit. assumenda voluptas deleniti at, molestias in amet dolore voluptatem atque, modi minus ipsam dignissimos...',
          scrollheight: 0,
        }
    }

    onchange(e) {
      const t = e.target;
      t.style.height = 'auto';
      t.style.height = `${t.scrollheight}px`;
      this.setstate({value: t.value});
    }

    render() {
        return (
            <styledtextarea
              value={this.state.value}
              onchange={this.onchange.bind(this)}
            />
        );
    }
}

class textarea2 extends react.component {

    constructor(props) {
        super(props);
        this.state = {
          value: 'lorem ipsum dolor sit amet, consectetur adipisicing elit. assumenda voluptas deleniti at, molestias in amet dolore voluptatem atque, modi minus ipsam dignissimos...',
          scrollheight: 0,
        }
    }

    onchange(e) {
      const bugger = e.target;
       console.log('style.height before it is set to auto: ', bugger.style.height)
      bugger.style.height = 'auto';
       console.log('style.height after it is set to auto (obviously): ', bugger.style.height)
       console.log('.scroll height: ', bugger.scrollheight);
      this.setstate({
        scrollheight: bugger.scrollheight,
        value: bugger.value
      });
      // another update here
      bugger.style.height = '';
    }

    render() {
      console.log(this.state.scrollheight);
        return (
            <styledtextarea
              style={{height: this.state.scrollheight}}
              value={this.state.value}
              onchange={this.onchange.bind(this)}
            />
        );
    }
}

reactdom.render(<app />, document.getelementbyid('root'));

a final note, the second approach you are using is definitely the more preferable one! modifying your components styles via a handler as opposed to the render method is not ideal.


Related Query

More Query from same tag