Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React doesn't focus conditionally rendered input/textarea

I'm trying to focus() a conditionally rendered textarea in React. The code below is almost exactly identical to the example in the React docs or to this similar question.

The code below immediately shows and focuses the textarea. If the three commented lines are uncommented, the textarea gets shown after the condition prop is set to true (its value depends on the state of the parent and is initially false), but the element doesn't get focused anymore.

If the condition is initially true, the input element gets focused as expected when the component renders for the first time. The problem occurs when the condition is changed from false to true.

import React, { Component } from 'react'

class TestClass extends Component {
  constructor(props) {
    super(props)
    this.focus = this.focus.bind(this)
  }
  componentDidMount() {
    // this.props.condition &&
    this.focus()
  }
  componentDidUpdate() {
    // this.props.condition &&
    this.focus()
  }

  focus() {
    console.log(`this.textInput: ${this.textInput}`)
    this.textInput.focus()
  }

  render() {
    return (
      <div>
        {
          // this.props.condition &&
          <textarea
            ref={(input) => {this.textInput = input}}
            defaultValue="Thanks in advance for your invaluable advice">
            {console.log('textarea rendered')}
          </textarea>
        }
      </div>
    )
  }
}

The console output

textarea rendered
this.textInput: [object HTMLTextAreaElement]

rules out that the element is unavailable at the time focus() gets executed.

Furthermore:

  • Setting autoFocus attribute doesn't seem to work, in contrast to this question
  • Same problem for both <input /> and <textarea />

Edit: in response to the question below, the parent component looks as follows.

class ParentComponent extends Component {
  constructor(props) {
  super(props)
    this.state = {
      condition: false
    }
    this.toggleCondition = this.toggleCondition.bind(this)
  }
  toggleCondition() {
    this.setState(prevState => ({
      condition: !prevState.condition
    }))
  }
  render() {
    return (
      <div>
        <TestClass condition={this.state.condition} />
        <button onMouseDown={this.toggleCondition} />
      </div>
    )
  }
}
like image 598
Bart Avatar asked Jan 28 '26 02:01

Bart


1 Answers

import React, { Component } from 'react';

class TestClass extends Component {
  constructor(props) {
    super(props);
    this.focus = this.focus.bind(this);
  }
  componentDidMount() {
    this.focus();
  }
  componentWillReceiveProps(nextProps) {
    if (nextProps.condition !== this.props.condition) {
        this.focus();  
    }
  }
  focus() {
    console.log(`this.textInput: ${this.textInput}`);
    if (this.props.condition === true) {
      this.textInput.focus();
    }
  }

  render() {
    return (
      <div>
        {
          this.props.condition &&
          <textarea
            ref={(input) => { this.textInput = input; }}
            defaultValue="Thanks in advance for your invaluable advice"
          >
            {console.log('textarea rendered')}
          </textarea>
        }
      </div>
    );
  }
}
export default TestClass;
like image 143
Dinesh Katwal Avatar answered Jan 29 '26 16:01

Dinesh Katwal



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!