【问题标题】:React doesn't focus conditionally rendered input/textareaReact 不关注有条件渲染的输入/文本区域
【发布时间】:2017-12-29 19:03:00
【问题描述】:

我正在尝试focus() React 中的条件渲染文本区域。下面的代码与React docs 或this similar question 中的示例几乎完全相同。

下面的代码立即显示并聚焦文本区域。如果三个注释行未注释,则在 condition 属性设置为 true 后显示 textarea(其值取决于父级的状态,最初为 false),但元素没有获得焦点没有了。

如果条件最初为true,则当组件第一次呈现时,输入元素会按预期获得焦点。当条件从false 更改为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>
    )
  }
}

控制台输出

textarea rendered
this.textInput: [object HTMLTextAreaElement]

排除在执行focus() 时该元素不可用。

此外:

  • 与this question 相比,设置autoFocus 属性似乎不起作用
  • &lt;input /&gt; 和 &lt;textarea /&gt; 的问题相同

编辑:针对下面的问题,父组件如下所示。

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>
    )
  }
}

【问题讨论】:

  • 如果您在 componentDidMount 和 componentDidUpdate 中将 this.props.condition &amp;&amp; 替换为更详细的 if(this.props.condition) { },这会以任何方式改变行为吗?
  • 不幸的是,没有。在 JavaScript 中,true &amp;&amp; expression 始终计算为 expression,false &amp;&amp; expression 始终计算为 false。 (来源:facebook.github.io/react/docs/…)
  • 您可以添加您的父组件代码,即添加 TestClass 组件吗?我认为问题可能在于您如何将“条件”作为道具传递,如果我使用&lt;TestClass condition="true"/&gt; 将其作为字符串传递,它不起作用,但是将条件作为布尔标志传递对我有用:&lt;TestClass condition/&gt;
  • 我的猜测是问题在于最初的条件是false。如果我将条件最初设置为true,它会起作用。条件是布尔值,但我会在一分钟后发布父类。
  • 我已经在操场上测试了你的代码。 TestClass 按照您的预期正确更新。 this.focus 在每次切换时执行。也许我做错了什么,没有得到问题。能否提供一些其他细节?

标签: javascript reactjs focus textarea


【解决方案1】:
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;

【讨论】:

  • 谢谢,但是当我尝试这个时,this.textInput 是 undefined,而 componentWillReceiveProps 被调用。
  • 如果 this.textInput 未定义,则 this.textInput.focus() 不会触发。
  • 这是什么问题:-)
  • 这是你所期待的。
  • 请查看来源。
【解决方案2】:

原来这个问题真的很愚蠢。我实现切换按钮的方式(我在原始问题“为清楚起见”中简化为&lt;button onClick={this.toggleCondition} /&gt;)是使用自定义组件,该组件采用onClick 属性并将其值附加到超链接的onMouseDown 属性.

由于超链接在其onMouseDown 操作后获得焦点,因此焦点立即从文本区域移开。

我已编辑问题以反映我对 onMouseDown 的使用情况。

【讨论】:

  • 我的解决方案有什么问题。
  • 问题出在父组件中。不过,您的代码独立于父组件工作。我会赞成的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-30
  • 2020-05-05
  • 2019-11-18
  • 2018-04-07
  • 2020-04-18
  • 2020-10-03
  • 1970-01-01
相关资源
最近更新 更多