javascriptreactjsdom-eventsonkeyuponpaste

React JS: onPaste not working as expected


I have a simple React component for a textarea that increases its size as the user types into it. The function looks like this:

changeHeight(e) {
    const height = this.textarea.clientHeight;
    const scrollHeight = this.textarea.scrollHeight;
    if (height < scrollHeight) {
        this.textarea.style.height = scrollHeight + "px";
    }
}

When I use onKeyUp to call this function on the textarea it works fine, however if I change it to onPaste then the function gets called (if you console.log something), but no height is added to the textarea as expected.

Is there something obvious which I'm missing here?

Here's the full code:

class Textarea extends React.Component {

    constructor(props) {
    super(props);
    this.changeHeight = this.changeHeight.bind(this);
  }

    changeHeight(e) {
        const height = this.textarea.clientHeight;
        const scrollHeight = this.textarea.scrollHeight;
        if (height < scrollHeight) {
            this.textarea.style.height = scrollHeight + "px";
        }
        console.log("changeHeight");
    }

    render() {
        const {input, label, type, optional, value, helperText, meta: { touched, error }, ...custom } = this.props;
        return (
            <div className="measure mb4">
                <label for="name" className="f6 b db mb2">{label} {optional ? <span className="normal black-60">(optional)</span> : null}</label>
                <textarea onPaste={this.changeHeight} ref={(el) => { this.textarea = el; }} className={"input-reset ba b--black-20 pa2 mb2 db w-100 border-box lh-copy h5 animate-h"} aria-describedby="name-desc" {...input} {...custom} value={value} />
                {touched && error ? <small id="name-desc" className="f6 red db mb2">{error}</small> : null}
                {helperText ? <small id="name-desc" className="f6 black db mb2">{helperText}</small> : null}
            </div>
        )
    }

}

Solution

  • Thanks to Teemu for posting the answers in the comments:

    Changing the event to onInput works as expected (event is triggered for when the user types and pastes). Updated code:

    class Textarea extends React.Component {
    
        constructor(props) {
        super(props);
        this.changeHeight = this.changeHeight.bind(this);
      }
    
        changeHeight(e) {
            const height = this.textarea.clientHeight;
            const scrollHeight = this.textarea.scrollHeight;
            if (height < scrollHeight) {
                this.textarea.style.height = scrollHeight + "px";
            }
            console.log("changeHeight");
        }
    
        render() {
            const {input, label, type, optional, value, helperText, meta: { touched, error }, ...custom } = this.props;
            return (
                <div className="measure mb4">
                    <label for="name" className="f6 b db mb2">{label} {optional ? <span className="normal black-60">(optional)</span> : null}</label>
                    <textarea onInput={this.changeHeight} ref={(el) => { this.textarea = el; }} className={"input-reset ba b--black-20 pa2 mb2 db w-100 border-box lh-copy h5 animate-h"} aria-describedby="name-desc" {...input} {...custom} value={value} />
                    {touched && error ? <small id="name-desc" className="f6 red db mb2">{error}</small> : null}
                    {helperText ? <small id="name-desc" className="f6 black db mb2">{helperText}</small> : null}
                </div>
            )
        }
    
    }