8

I am trying to select all the text in a textarea when a component loads using React v16.3.1

Following the Refs docs I have a basic sample but this.textarea is always undefined, if I change this sample to execute the same code on a button click it works fine.

So whats going on? I had expected that after mounting the component should be available?

Sample code:

import React from "react";

class Hello extends React.Component {
  constructor(props) {
    super(props);
    this.textarea = React.createRef();
  }

  componentDidMount = () => {
    this.textarea.current.select();
  };

  render() {
    return (
      <div>
        <textarea
          className="form-control"
          defaultValue="the quick brown fox."
          ref={this.textarea}
        />
      </div>
    );
  }
}

From package.json:

"react": "^16.3.1",
"react-dom": "^16.3.1",

Thanks

shenku
  • 10,902
  • 11
  • 61
  • 113
  • It's working correctly for me, are you sure you have the correct version of react? – Axnyff Apr 15 '18 at 07:34
  • What if you change arrow function? `componentDidMount() { this.textarea.current.select(); };` – Tomasz Mularczyk Apr 15 '18 at 07:37
  • @Axnyff yup, 16.3.1 is the version installed... – shenku Apr 15 '18 at 09:23
  • @TomaszMularczyk no change – shenku Apr 15 '18 at 09:30
  • @shenku I have the same issue, did you find out what was wrong? I'm using 16.8.2 – HRK44 Feb 18 '19 at 13:21
  • Ok I fixed my code using this answer https://stackoverflow.com/questions/44074747/componentdidmount-called-before-ref-callback/50019873#50019873 Basically, ref will be null if the component is not rendered (for example if you return a loading item or something like that). So I just use hide/show logic instead of not returning my referenced element. – HRK44 Feb 18 '19 at 16:48

1 Answers1

3

The documentation says:

Note

The examples below have been updated to use the React.createRef() API introduced in React 16.3. If you are using an earlier release of React, we recommend using callback refs instead.

If you are using an earlier release of React, u need use callback refs

class App extends React.Component {
  constructor(props) {
    super(props);
    this.textarea = null;

    this.setTextareaRef = element => {
      this.textarea = element;
    };
  }

  componentDidMount = () => {
    if (this.textarea) this.textarea.select();
  };

  render() {
    return (
      <div>
        <textarea
          className="form-control"
          defaultValue="the quick brown fox."
          ref={this.setTextareaRef}
        />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Using React 16.3

class App extends React.Component {
  constructor(props) {
    super(props);
    this.textarea = React.createRef();
  }

  componentDidMount = () => {
    this.textarea.current.select();
  };

  render() {
    return (
      <div>
        <textarea
          className="form-control"
          defaultValue="the quick brown fox."
          ref={this.textarea}
        />
      </div>
    );
  }
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://unpkg.com/react@16.3.1/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.3.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Community
  • 1
  • 1
NoobSaibot
  • 204
  • 1
  • 2
  • 10
  • okay some progress, if I remove all my existing application logic and use as above it works, but when I use it with react-router etc. it just doesn't work - can't figure this one out, but you are correct it works as a simple component. – shenku Apr 15 '18 at 09:49
  • Tested using **react-router-dom**: https://stackblitz.com/edit/react-hmasqk?file=index.js – NoobSaibot Apr 15 '18 at 11:32