【问题标题】:how react programmatically focus input如何以编程方式反应焦点输入
【发布时间】:2017-08-26 00:18:28
【问题描述】:

我正在尝试实现一个非常简单的用例,一个 UI 功能,其中:

  1. 有一个标签,里面有一些内容
  2. 如果单击,文本输入将其替换为可用标签的内容
  3. 用户可以编辑内容
  4. 按下回车后,输入隐藏,标签返回更新内容

我终于可以完全正确(实际上是使用 MongoBD 后端、redux 等),而我唯一不能做的事情(花一整天时间在谷歌上搜索和阅读 SOF 类似帖子)是这样的:

当我的文本输入出现时,我无法将焦点转移到它!首先我是这样累的:

<div className={((this.state.toggleWordEdit) ? '' : 'hidden')}>
<input id={this.props.word._id} className="form-control"
        ref="updateTheWord" 
        defaultValue={this.state.word}
        onChange={this.handleChange}
        onKeyPress={this.handleSubmit}
        autoFocus={this.state.toggleWordEdit}/></div>
    <div className={((this.state.toggleWordEdit) ? 'hidden' : '')}>
      <h3 onClick={this.updateWord}>
        {this.state.word}</h3>
    </div>

但 autoFocus 肯定不起作用(我“猜”是因为表单已呈现,但处于隐藏状态,使 autoFocus 无用)。

接下来我在我的 this.updateWor 中尝试了很多我在 google 和 S.O.F. 上找到的建议:

this.refs.updateTheWord.focus();

连同类似的建议都没有奏效。我还试图愚弄 React 只是为了看看我能不能做点什么!我用的是真实的 DOM:

    const x = document.getElementById(this.props.word._id);
    x.focus();

它也没有工作。我什至无法理解的一件事是这样的建议: having ref as a method (I "guess") 我什至没有尝试过,因为我有多个这些组件,我需要 ref 来进一步获取每个组件的值,我无法想象如果我的 ref 没有命名,我怎么能得到值!

所以您能否提供一个想法,帮助我理解如果我不使用表单(因为我需要一个输入框替换标签),当它是 CSS(引导)类时,我如何设置它的焦点请问是丢失“隐藏”吗?

【问题讨论】:

  • 这行得通吗? c.focus()} />
  • 在这种情况下,一旦输入被渲染,由 ref 定义的回调将被执行,并传入对当前元素的引用。您可以使用此回调函数来定义对 dom 节点的引用 - 例如 ref={c => this.refs.c = c}。然后,你就可以正常使用 this.refs 了(只要确保它是事先定义好的)。

标签: reactjs input focus


【解决方案1】:

您使用 refs 的方式不是最优选的方式,否则它不再是最佳实践。试试这样的事情

class MyClass extends React.Component {
  constructor(props) {
    super(props);
    this.focus = this.focus.bind(this);
  }

  focus() {
    this.textInput.current.focus();
  }

  render() {

    return (
      <div>
        <input
          type="text"
          ref={(input) => { this.textInput = input; }} />
        <input
          type="button"
          value="Set Focus"
          onClick={this.focus}
        />
      </div>
    );
  }
}

更新
React 16.3 起,您可以使用 React.createRef() API

class MyClass extends React.Component {
  constructor(props) {
    super(props);
    // create a ref to store the textInput DOM element
    this.textInput = React.createRef();
    this.focus = this.focus.bind(this);
  }

  focus() {
    // Explicitly focus the text input using the raw DOM API
    // Note: we're accessing "current" to get the DOM node
    this.textInput.current.focus();
  }

  render() {
    // tell React that we want to associate the <input> ref
    // with the `textInput` that we created in the constructor
    return (
      <div>
        <input
          type="text"
          ref={this.textInput} />
        <input
          type="button"
          value="Set Focus"
          onClick={this.focus}
        />
      </div>
    );
  }
}

【讨论】:

  • 如果我有一个输入字段列表并且想在用户点击输入时关注下一个输入字段,我将如何动态执行此操作?
  • @AvremelKaminetzky 您是否找到了解决焦点问题的方法?如果我正确理解您的评论,我会遇到类似的问题。我有一个无状态 React 组件InputStepper,它应该关注加载时的第一个输入,然后在 keyup 之后将焦点移动到下一个 InputStepper 输入。但是,我看到输入焦点然后失去焦点。当我检查元素 &lt;input ... autofocus /&gt; 已设置但它仍然没有保持焦点。这是 React 和表单/输入和焦点的问题吗?
  • @Anovative 我不记得细节了,但这是我的(hacky)解决方案:stackoverflow.com/a/46777890/4822174
  • 如果不起作用,尤其是对于较新的 React,请尝试使用 inputRef 而不是 ref。我可以以编程方式关注TextField
  • 有没有使用函数组件的实现?
【解决方案2】:

只需将autofocus 属性添加到input。 (当然在JSXautoFocus

<input autoFocus ...

【讨论】:

  • 如果您想动态地自动对焦,例如单击一键怎么办?!
  • @AhmedElbatt 您可以为此使用布尔状态,例如:&lt;input autoFocus={state.autoFocus} ... 并更改按钮单击时的状态。
【解决方案3】:

使用焦点挂钩

// General Focus Hook
const useFocus = (initialFocus = false, id = "") => {
    const [focus, setFocus] = useState(initialFocus)
    const setFocusWithTrueDefault = (param) => setFocus(isBoolean(param)? param : true)
    return ([
        setFocusWithTrueDefault, {
            autoFocus: focus,
            key: `${id}${focus}`,
            onFocus: () => setFocus(true),
            onBlur: () => setFocus(false),
        },
    ])
}


const FocusDemo = () => {

    const [labelStr, setLabelStr] = useState("Your initial Value")
    const [setFocus, focusProps] = useFocus(true)

    return (
        <> {/* React.Fragment */}
            <input
                onChange={(e)=> setLabelStr(e.target.value)}
                value={labelStr}
                {...focusProps}
            />
            <h3 onClick={setFocus}>{labelStr}</h3>
        </>
    )
    
}

获取更完整的演示 click here

【讨论】:

  • 似乎没有完整演示的链接。它在某处可用吗?
  • @llamerr,今天我更喜欢类似但略有不同的方法:stackoverflow.com/questions/28889826/…。从理论上讲,我更喜欢它,因为它更短且更容易理解,但实际上,从我的经验来看,它似乎在长列表上工作得更好。请试一试,让我知道你的想法。如果您同意,我也会在这里更新我的解决方案。某处可能有此解决方案的演示,或者如果您仍然认为有必要,我可以准备一个。
  • 这个工作。谢谢!
【解决方案4】:

除了之前的答案,我还添加了setTimeout 以使其正常工作

handleClick() {


    if (this.searchInput) {
        setTimeout(() => {

            this.searchInput.focus();

        }, 100);
    }
}

searchInput 是输入的 jsx 引用

<input
      type="text"
      name="searchText"
      ref={(input) => { this.searchInput = input; }}
      placeholder="Search" />

handleClick() 是任何元素的 onClick 处理程序

【讨论】:

    【解决方案5】:

    @BenCarp 在打字稿中的回答

    inputRef 传递给input,然后调用setFocus 将焦点设置在它上面。

    export const useInputFocus = (): [MutableRefObject<HTMLInputElement | undefined>, () => void] => {
      const inputRef = useRef<HTMLInputElement>();
      const setFocus = (): void => {
        const currentEl = inputRef.current;
        if (currentEl) {
          currentEl.focus();
        }
      };
      return [inputRef, setFocus];
    };
    

    【讨论】:

      【解决方案6】:

      每次更新组件时使用componentDidUpdate方法

      componentDidUpdate(prevProps, prevState) {
           this.input.focus();
      }
      

      【讨论】:

        【解决方案7】:

        您可以使用“useRef”挂钩并引用您的输入控件,然后使用您的reference.current.focus()

        您可以观看视频作为示例:

        https://www.youtube.com/watch?v=LPL440Yrl8s

        【讨论】:

        • 视频不可用
        猜你喜欢
        • 2020-02-15
        • 2011-12-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-02
        • 2011-12-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多