TypeError: this.textInput is undefined React

I tried to make input focused when component render. I copied from React doc example https://reactjs.org/docs/refs-and-the-dom.html

My version:

class CreateTask extends React.Component {
      constructor(props){
        super(props);
      }
      componentDidMount(){
       this.textInput.focus();
     }
      render (){
        if (this.props.visibility == true){
        return(
          <div className="new_task_form">
            <h2>New task</h2>
            <input type="text" ref={(input) => { this.textInput = input; }} onChange={this.props.handleEdit} value={this.props.messageValue} />
            <div>);
        }
 }

I am always getting the same error message - TypeError: this.textInput is undefined. Did anyone came across the same issue? Any help is much appreciated!

Hi Anastasyya, that’s happening to you because the variable “this.textInput” haven’t been defined, you should define it before in the constructor of the class, that way you will be sure that the variable is available every time you need it.

1 Like

Thank you @ejas94 ! I thought constructor of the class can be used to define only methods. I am not sure how can I define a variable. Can you please show how the definition of a variable will look like in my case?

For JavaScript you defined variables in the constructor in this way: this.variableName = value.
So in this case you can just define it like this.textInput; so when the render method is called it will find the variable and won’t give you the error.

1 Like
class CreateTask extends React.Component {
      constructor(props){
        super(props);
        this.textInput;
      }
      componentDidMount(){
       this.textInput.focus();
     }
      render (){
        if (this.props.visibility == true){
        return(
          <div className="new_task_form">
            <h2>New task</h2>
            <input type="text" ref={(input) => { this.textInput = input; }} onChange={this.props.handleEdit} value={this.props.messageValue} />
            <div>

Unfortunately, it still returns the same error message:

TypeError: this.textInput is undefined

Which line is giving you the error? Could you paste the complete error log?

Sure:

Link learn more https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Unexpected_type

Get rid of the focus in componentDidMount; its that that will be erroring. It looks like the ref is registered after it mounts, which means that the DOM reference to the input doesn’t exist when that method is called. If you look at the example you’ve modified, it’s not using componentDidMount, it’s accessing the DOM after a button is clicked.

Add an autofocus attribute to the input element if you want it to focus on page load: this is built.into HTML5, you don’t need to use JS to try to emulate it.

1 Like

I used autoFocus=“autofocus” for now. It does the same thing in this situation, but I am still not sure why this.textInput.focus() didn’t work.

Thank you @DanCouper! That makes sense and solves my question. I will go with autoFocus instead.

Hah, snap! But yeah, now you can use the ref to grab the value from the input, you can use a method that is fired onInput or onChange, and this.textInput.value will be the right value inside that method.

1 Like

Is in the componentDidMount method, so that means is after the render method. The render method have a conditional saying this.props.visibility === true, if this prop is not true then the input is not rendered and the textInput variable will be undefined. If you delete this conditional just for testing it should work.

1 Like

Ah that kinda makes sense. I just wondered whether the function that registers the ref inside that prop wouldn’t be fired until it needed to be, so the reference in componentDidMount wouldn’t be valid.

True, it works without the condition. If I remove it, everything is working perfectly :slight_smile: Thank you!

Good to see is working now, next step is conditionally decide when a variable is available in the componentDidMount method (or another place where you need it) so that way if you haven’t defined it, it won’t break the code :slight_smile: