Установка фокуса на ввод после рендеринга

каков способ react установки фокуса на определенном текстовом поле после отрисовки компонента?

документация, похоже, предлагает использовать refs, e.g:

Set ref="nameInput" в моем поле ввода в функции рендеринга, а затем вызовите:

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

но где я должен это назвать? Я пробовал несколько мест, но не могу заставить его работать.

19 ответов


вы должны сделать его в componentDidMount и refs callback вместо. Что-то вроде этого!--8-->

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

class App extends React.Component{
  componentDidMount(){
    this.nameInput.focus();
  }
  render() {
    return(
      <div>
        <input 
          defaultValue="Won't focus" 
        />
        <input 
          ref={(input) => { this.nameInput = input; }} 
          defaultValue="will focus"
        />
      </div>
    );
  }
}
    
ReactDOM.render(<App />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.js"></script>
<div id="app"></div>

@Dhiraj является правильным, и для удобства вы можете использовать автофокус опора на вход автоматической фокусировки при монтаже:

<input autoFocus name=...

обратите внимание, что в jsx это autoFocus (capital F) в отличие от обычного старого html, который не учитывает регистр.


по состоянию на 0.15, самый краткий метод:

<input ref={input => input && input.focus()}/>

Если вы просто хотите сделать автофокус в React, это просто.

<input autoFocus type="text" />

а если вы просто хотите знать, куда поместить этот код, ответ в componentDidMount().

v014.3

componentDidMount() {
    this.refs.linkInput.focus()
}

в большинстве случаев вы можете прикрепить ссылку к узлу DOM и вообще избежать использования findDOMNode.

прочитайте документы API здесь: https://facebook.github.io/react/docs/top-level-api.html#reactdom.finddomnode


Я только что столкнулся с этой проблемой, и я использую react 15.0.1 15.0.2 и я использую синтаксис ES6 и не совсем получил то, что мне нужно от других ответов, так как v. 15 упал несколько недель назад и некоторые из this.refs свойства были устаревшими и удалены.

в общем, мне нужно было:

  1. сфокусируйте первый элемент ввода (поля), когда компонент монтируется
  2. сфокусировать первый вход (поле) элемент с ошибкой (после отправки)

я:

  • React Контейнер / Компонент Презентации
  • Redux
  • React-Маршрутизатор

сфокусировать первый входной элемент

я autoFocus={true} первый <input /> на странице, чтобы, когда компонент монтируется, он получал фокус.

фокус первого входного элемента с ошибкой

это заняло больше времени и было больше извилистый. Я держу код, который не имеет отношения к решению для краткости.

Redux Store / State

мне нужно глобальное состояние, чтобы знать, должен ли я установить фокус и отключить его, когда он был установлен, поэтому я не продолжаю переустанавливать фокус, когда компоненты перерисовываются (я буду использовать componentDidUpdate() чтобы проверить настройку фокуса.)

это может быть разработан как вы считаете нужным для вас приложением.

{
    form: {
        resetFocus: false,
    }
}

Контейнер Компонент

в компонент должен будет иметь resetfocus набор свойств и обратный вызов, чтобы очистить свойство, если он в конечном итоге установка фокуса на себя.

также обратите внимание, что я организовал своих создателей действий в отдельные файлы в основном из-за моего проекта довольно большой, и я хотел разбить их на более управляемые куски.

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. Затем, когда каждый компонент обновит себя, он увидит, что он должен проверить, получает ли он фокус, и если да, отправьте событие для сброса фокуса, чтобы другим элементам не нужно было продолжать проверку.

редактировать В качестве примечания, у меня была моя бизнес-логика в файле "утилиты", и я просто экспортировал метод и вызывал его в каждом shouldfocus() метод.

Ура!


в документах React теперь есть раздел для этого. https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute

 render: function() {
  return (
    <TextInput
      ref={function(input) {
        if (input != null) {
          input.focus();
        }
      }} />
    );
  },

Ref. Комментарий @ Dave к ответу @Dhiraj; альтернативой является использование функции обратного вызова атрибута ref для отображаемого элемента (после того, как компонент сначала отображает):

<input ref={ function(component){ React.findDOMNode(component).focus();} } />

Подробнее


это правильный способ, как автофокус. При использовании обратного вызова вместо строки в качестве значения ref он вызывается автоматически. Вы получили ваш ref доступен, чем без необходимости прикасаться к DOM с помощью getDOMNode

render: function() {
  return <TextInput ref={(c) => this._input = c} />;
},
componentDidMount: function() {
  this._input.focus();
},

это уже не лучший ответ. Как на версии v0.13, this.refs может быть недоступно доcomponentDidMount() выполняется, в некоторых нечетных случаях.

просто добавить autoFocus тег в поле ввода, как показано выше FakeRainBrigand.


вы можете поместить этот вызов метода внутри функции render. Или внутри метода жизненного цикла, componentDidUpdate


обратите внимание, что ни один из этих ответов работал для меня материал-компонент текстового поля пользовательского интерфейса. Пер Как установить фокус на текстовое поле materialUI? мне пришлось прыгать через некоторые обручи, чтобы заставить это работать:

const focusUsernameInputField = input => {
  if (input) {
    setTimeout(() => {input.focus()}, 100);
  }
};

return (
  <TextField
    hintText="Username"
    floatingLabelText="Username"
    ref={focusUsernameInputField}
  />
);

не нужно 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'));

автофокус работал лучше для меня. Мне нужно было изменить текст на ввод с этим текстом при двойном щелчке, так что это то, что я закончил:

<input autoFocus onFocus={this.setCaretToEnd} value={this.state.editTodo.value} onDoubleClick={this.updateTodoItem} />

Примечание: чтобы устранить проблему, когда React помещает курсор в начале текста, используйте этот метод:

setCaretToEnd(event) {
    var originalText = event.target.value;
    event.target.value = '';
    event.target.value = originalText;
}

найти здесь: https://coderwall.com/p/0iz_zq/how-to-put-focus-at-the-end-of-an-input-with-react-js


предупреждение: ReactDOMComponent: не получить доступ .getDOMNode () узла DOM; вместо этого используйте узел напрямую. Этот узел DOM был отображен App.

должно быть

componentDidMount: function () {
  this.refs.nameInput.focus();
}

самый простой ответ-добавить ref= "некоторое имя" во входном текстовом элементе и вызвать функцию ниже.

componentDidMount(){
   this.refs.field_name.focus();
}
// here field_name is ref name.

<input type="text" ref="field_name" />

У меня такая же проблема, но у меня тоже есть анимация, поэтому мой коллега предлагает использовать окно.метод requestAnimationFrame

это атрибут ref моего элемента:

ref={(input) => {input && window.requestAnimationFrame(()=>{input.focus()})}}

прочитайте почти весь ответ, но не видели getRenderedComponent().props.input

установите ввод текста refs

this.refs.username.getRenderedComponent().props.input.onChange('');


попробовав много вариантов выше без успеха, я обнаружил, что это было так, как я был disabling а то enabling вход, что вызвало фокус теряются.

у меня был проп 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.
/>

как только я удалил отключенную опору, все снова начало работать.


обновленная версия, вы можете проверить здесь

componentDidMount() {

    // Focus to the input as html5 autofocus
    this.inputRef.focus();

}
render() {
    return <input type="text" ref={(input) => { this.inputRef = input }} />
})