Фокусировка элементов div с помощью React

Можно ли сфокусировать div (или любые другие элементы) с помощью метода focus()?

Я установил tabIndex в элемент div:

<div ref="dropdown" tabIndex="1"></div>

И я вижу, что он фокусируется, когда я нажимаю на него, однако я пытаюсь динамически сфокусировать элемент следующим образом:

setActive(state) {
  ReactDOM.findDOMNode(this.refs.dropdown).focus();
}

Или вот так:

this.refs.dropdown.focus();

Но компонент не получает фокус при срабатывании события. Как я могу это сделать? Есть ли какой-нибудь другой (не входной) элемент, который я могу использовать для этого?

EDIT:

Ну, похоже, это действительно можно сделать: https://jsfiddle.net/69z2wepo/54201/

Но это не работает для меня, это мой полный код:

class ColorPicker extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      active: false,
      value: ""
    };
  }

  selectItem(color) {
    this.setState({ value: color, active: false });
  }

  setActive(state) {
    this.setState({ active: state });
    this.refs.dropdown.focus();
  }

  render() {
    const { colors, styles, inputName } = this.props;

    const pickerClasses = classNames('colorpicker-dropdown', { 'active': this.state.active });

    const colorFields = colors.map((color, index) => {
      const colorClasses = classNames('colorpicker-item', [`colorpicker-item-${color}`]);

      return (
        <div onClick={() => { this.selectItem(color) }} key={index} className="colorpicker-item-container">
          <div className={colorClasses}></div>
        </div>
      );
    });

    return (
      <div className="colorpicker">
        <input type="text" className={styles} name={inputName} ref="component" value={this.state.value} onFocus={() => { this.setActive(true) }} />
        <div onBlur={() => this.setActive(false) } onFocus={() => console.log('focus')} tabIndex="1" ref="dropdown" className={pickerClasses}>
          {colorFields}
        </div>
      </div>
    );
  }
}

Ответ 1

Реакция перерисовывает компонент каждый раз, когда вы устанавливаете состояние, что означает, что компонент теряет фокус. В подобных случаях удобно использовать методы componentDidUpdate или componentDidMount, если вы хотите сфокусировать элемент на основе элемента prop или state.

Имейте в виду, что в соответствии с документацией React Lifecycle componentDidMount произойдет только после визуализации компонента в первый раз на экране, а в этом вызове componentDidUpdate не произойдет, то для каждого нового setState forceUpdate или компонент, получающий новые реквизиты, вызовет вызов componentDidUpdate.

componentDidMount() {
  this.focusDiv();
},
componentDidUpdate() {
  if(this.state.active)
    this.focusDiv();
},
focusDiv() {
  ReactDOM.findDOMNode(this.refs.theDiv).focus();
}

Вот скрипт JS, с которым вы можете играть.

Ответ 2

В этом проблема:

this.setState({ active: state });
this.refs.component.focus();

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

this.setState({ active: state }, () => {
   this.refs.component.focus();
});

Ответ 3

Немного поздно, чтобы ответить, но причина, по которой ваш обработчик событий не работает, возможно, в том, что вы не привязываете свои функции, и поэтому "this", используемое внутри функции, будет неопределенным, если вы передадите его, например: "this.selectItem(color) "

В конструкторе делаем:

this.selectItem = this.selectItem.bind(this)

this.setActive = this.setActive.bind(this)

Ответ 4

import React from "react"
import ReactDOM from 'react-dom';

export default class DivFocusReactJs extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
    }
  }

  componentDidMount() {
    ReactDOM.findDOMNode(this.refs.divFocus).focus();
  }

  render() {
    return (
      <div tabIndex={1} ref="divFocus">
        <p>Focusing div elements with React</p>
        {/*your code here...*/}
      </div>
    )
  }
}

Ответ 5

Это работало в моем случае

render: function(){

  if(this.props.edit){
    setTimeout(()=>{ this.divElement.focus() },0)
  }

    return <div ref={ divElement => this.divElement = divElement}
                contentEditable={props.edit}/>
}

Ответ 6

Не уверен, что это правильный путь, но я обнаружил, что это работает для меня.

render() {
  return <div ref='item' onLoad={() => this.refs.item.focus()}>I will have focus</div>
}