javascript - React doesn't focus conditionally rendered inputtextarea - Stack Overflow

I'm trying to focus() a conditionally rendered textarea in React. The code below is almost exactly

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 mented lines are unmented, 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 ponent 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)
  }
  ponentDidMount() {
    // this.props.condition &&
    this.focus()
  }
  ponentDidUpdate() {
    // 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 ponent 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>
    )
  }
}

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 mented lines are unmented, 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 ponent 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)
  }
  ponentDidMount() {
    // this.props.condition &&
    this.focus()
  }
  ponentDidUpdate() {
    // 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 ponent 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>
    )
  }
}
Share Improve this question edited Jul 24, 2017 at 10:59 Bart asked Jul 24, 2017 at 9:05 BartBart 1,6092 gold badges14 silver badges29 bronze badges 10
  • If you substitute your this.props.condition && for a more verbose if(this.props.condition) { } in both ponentDidMount and ponentDidUpdate does this change the behaviour in any way? – Finbarr O'B Commented Jul 24, 2017 at 9:21
  • Unfortunately, no. In JavaScript, true && expression always evaluates to expression, and false && expression always evaluates to false. (Source: facebook.github.io/react/docs/…) – Bart Commented Jul 24, 2017 at 9:25
  • Can you add your parent ponent code which is adding the TestClass ponent? I think the problem may lie in how you are passing 'condition' as a prop, if I pass it as a string using <TestClass condition="true"/>, it doesn't work, however passing condition as a boolean flag works for me: <TestClass condition/> – Finbarr O'B Commented Jul 24, 2017 at 9:36
  • My guess is that the problem lies with the condition being initially false. If I set the condition to be initially true, it works. The condition is a boolean, but I will post the parent class in a minute. – Bart Commented Jul 24, 2017 at 9:40
  • I've tested your code in playground. TestClass updates properly as you expect. this.focus executes on every toggling. Maybe I got something wrong and didn't get the question. Can you provides some other details? – Slowyn Commented Jul 24, 2017 at 10:22
 |  Show 5 more ments

2 Answers 2

Reset to default 3
import React, { Component } from 'react';

class TestClass extends Component {
  constructor(props) {
    super(props);
    this.focus = this.focus.bind(this);
  }
  ponentDidMount() {
    this.focus();
  }
  ponentWillReceiveProps(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;

Turns out the problem was really really stupid. The way I implemented the toggle button (which I simplified to <button onClick={this.toggleCondition} /> in the original question "for clarity"), was with a custom ponent which takes the onClick prop and attaches its value to the onMouseDown attribute of a hyperlink.

Because the hyperlink gets focused after its onMouseDown action, the focus was immediately taken away from the textarea.

I've edited the question to reflect my usage of onMouseDown.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744219610a4563717.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信