在组件渲染后,react如何设置聚焦在特定文本字段上?

文档似乎建议使用参考,例如:

在渲染函数的输入字段上设置ref="nameInput",然后调用:

this.refs.nameInput.getInputDOMNode().focus(); 

但是我该把它叫什么呢?我在几个地方试过了,但都不行。


当前回答

@Dhiraj的答案是正确的,为了方便,你可以使用自动对焦道具在安装时自动对焦:

<input autoFocus name=...

注意,在jsx中,它是自动聚焦(大写F),不像普通的旧html是不区分大小写的。

其他回答

我刚刚遇到了这个问题,我正在使用react 15.0.1 15.0.2,我正在使用ES6语法,并没有完全得到我需要的其他答案,因为v.15下降了几周前和一些这。Refs属性被弃用并移除。

总的来说,我需要的是:

当组件挂载时,关注第一个输入(字段)元素 关注带有错误的第一个输入(字段)元素(提交后)

我用的是:

React容器/表示组件 回来的 React-Router

聚焦第一个输入元素

我在页面上的第一个<input />上使用autoFocus={true},这样当组件挂载时,它就会得到焦点。

关注带有错误的第一个输入元素

这需要更长的时间,也更复杂。为了简洁起见,我省略了与解决方案无关的代码。

Redux Store / State

我需要一个全局状态来知道我是否应该设置焦点,并在它被设置时禁用它,这样我就不会在组件重新呈现时重新设置焦点(我将使用componentDidUpdate()来检查设置焦点)。

这可以根据您的应用程序进行设计。

{
    form: {
        resetFocus: false,
    }
}

容器组件

组件将需要设置resetfocus属性,如果它最终将焦点设置在自己身上,则需要使用callBack来清除该属性。

还要注意的是,我将我的Action creator组织到单独的文件中,主要是因为我的项目相当大,我想把它们分成更易于管理的块。

import { connect } from 'react-redux';
import MyField from '../presentation/MyField';
import ActionCreator from '../actions/action-creators';

function mapStateToProps(state) {
    return {
        resetFocus: state.form.resetFocus
    }
}

function mapDispatchToProps(dispatch) {
    return {
        clearResetFocus() {
            dispatch(ActionCreator.clearResetFocus());
        }
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(MyField);

表示组件

import React, { PropTypes } form 'react';

export default class MyField extends React.Component {
    // don't forget to .bind(this)
    constructor(props) {
        super(props);
        this._handleRef = this._handleRef.bind(this);
    }

    // This is not called on the initial render so
    // this._input will be set before this get called
    componentDidUpdate() {
        if(!this.props.resetFocus) {
            return false;
        }

        if(this.shouldfocus()) {
            this._input.focus();
            this.props.clearResetFocus();
        }
    }

    // When the component mounts, it will save a 
    // reference to itself as _input, which we'll
    // be able to call in subsequent componentDidUpdate()
    // calls if we need to set focus.
    _handleRef(c) {
        this._input = c;
    }

    // Whatever logic you need to determine if this
    // component should get focus
    shouldFocus() {
        // ...
    }

    // pass the _handleRef callback so we can access 
    // a reference of this element in other component methods
    render() {
        return (
            <input ref={this._handleRef} type="text" />
        );
    }
}

Myfield.propTypes = {
    clearResetFocus: PropTypes.func,
    resetFocus: PropTypes.bool
}

概述

一般的想法是,每个表单字段,可能有一个错误,并被集中需要检查自己,如果它需要设置自己的焦点。

需要执行业务逻辑来确定给定的字段是否是要设置焦点的正确字段。这里没有显示这一点,因为它取决于各个应用程序。

当提交表单时,该事件需要将全局焦点标志resetFocus设置为true。然后,当每个组件更新自己时,它会看到它应该检查它是否得到焦点,如果它得到了,分派事件重置焦点,这样其他元素就不必继续检查了。

编辑 作为旁注,我在一个“utilities”文件中有我的业务逻辑,我只是导出了这个方法,并在每个shouldfocus()方法中调用它。

干杯!

你不需要getInputDOMNode??在这种情况下……

当组件被挂载时,只需简单地获取ref和focus()它——componentDidMount…

import React from 'react';
import { render } from 'react-dom';

class myApp extends React.Component {

  componentDidMount() {
    this.nameInput.focus();
  }

  render() {
    return(
      <div>
        <input ref={input => { this.nameInput = input; }} />
      </div>
    );
  }

}

ReactDOM.render(<myApp />, document.getElementById('root'));

关注坐骑

如果你只是想在一个元素挂载(初始渲染)时聚焦它,简单使用autoFocus属性就可以了。

<input type="text" autoFocus />

动态焦点

要动态控制焦点,请使用通用函数对组件隐藏实现细节。

React 16.8 +功能组件- useFocus钩子

const FocusDemo = () => {

    const [inputRef, setInputFocus] = useFocus()

    return (
        <> 
            <button onClick={setInputFocus} >
               Focus
            </button>
            <input ref={inputRef} />
        </>
    )
    
}

const useFocus = () => {
    const htmlElRef = useRef(null)
    const setFocus = () => {htmlElRef.current &&  htmlElRef.current.focus()}

    return [ htmlElRef, setFocus ] 
}

完整的演示

React 16.3 +类组件-使用

class App extends Component {
  constructor(props){
    super(props)
    this.inputFocus = utilizeFocus()
  }

  render(){
    return (
      <> 
          <button onClick={this.inputFocus.setFocus}>
             Focus
          </button>
          <input ref={this.inputFocus.ref}/>
      </>
    )
  } 
}
const utilizeFocus = () => {
    const ref = React.createRef()
    const setFocus = () => {ref.current &&  ref.current.focus()}

    return {setFocus, ref} 
}

完整的演示

本卡普的解决方案在打字稿

React 16.8 +功能组件- useFocus钩子

export const useFocus = (): [React.MutableRefObject<HTMLInputElement>, VoidFunction] => {
  const htmlElRef = React.useRef<HTMLInputElement>(null);
  const setFocus = React.useCallback(() => {
    if (htmlElRef.current) htmlElRef.current.focus();
  }, [htmlElRef]);

  return React.useMemo(() => [htmlElRef, setFocus], [htmlElRef, setFocus]);
};

在尝试了上面的许多选项后,没有成功,我发现这是因为我禁用了输入,然后启用了输入,导致焦点丢失。

我有一个道具sendingAnswer将禁用输入,而我轮询后端。

<Input
  autoFocus={question}
  placeholder={
    gettingQuestion ? 'Loading...' : 'Type your answer here...'
  }
  value={answer}
  onChange={event => dispatch(updateAnswer(event.target.value))}
  type="text"
  autocomplete="off"
  name="answer"
  // disabled={sendingAnswer} <-- Causing focus to be lost.
/>

一旦我拆除了瘫痪的道具,一切又开始工作了。