Как обрабатывать фокус, используя библиотеки декларативного/функционального стиля, такие как Redux и ReactJS?

Оглядываясь, чтобы посмотреть, как другие разработчики справляются с фокусом ввода при работе с Redux, я столкнулся с некоторыми общими рекомендациями для компонентов ReactJS, таких как этот. Моя забота однако заключается в том, что функция focus() является обязательной, и я мог видеть странное поведение, когда несколько компонентов сражаются за фокус. Есть ли способ сокращения с фокусом? Кто-нибудь имеет дело с прагматичной настройкой фокуса с помощью сокращения и реагирования, и если да, то какие методы вы используете?

по теме:

Ответ 1

Мой подход использует обратный вызов ref, который является onRenderComplete элемента. В этом обратном вызове я могу сфокусироваться (условно, если необходимо) и получить ссылку для будущей фокусировки.

Если ввод выполняется условно после запуска действия, этот обратный вызов ref должен запускать фокус, поскольку ref не существует сразу после вызова действия, но только после выполнения рендеринга. Работа с componentDidUpdate для таких вещей, как focus, кажется просто беспорядком.

// Composer.jsx -- contains an input that will need to be focused somewhere else

class Composer extends Component {
  render() {
    return <input type="text" ref="input" />
  }

  // exposed as a public method
  focus() {
    this.refs.input.focus()
  }
}

// App.jsx

@connect(
  state => ({ isComposing: state.isComposing }),
  ...
)
class App extends Component {
  render() {
    const { isComposing } = this.props // or props, doesn't matter
    return (
      <div>
        <button onClick={::this._onCompose}>Compose</button>
        {isComposing ? <Composer ref={c => {
          this._composer = c
          this._composer && this._composer.focus() // issue initial focus
        }} /> : null}
      </div>
    )
  }

  _onCompose() {
    this.props.startComposing() // fire an action that changes state.isComposing

    // the first time the action dispatches, this._composer is still null, so the ref takes care of the focus. After the render, the ref remains so it can be accessed:

    this._composer && this._composer.focus() // focus if ref already exists
  }
}

Почему не autoFocus или isFocued prop?

Поскольку HTMLInputElement имеет value как prop, но focus() как метод - а не isFocused prop - я бы продолжал использовать методы для этого. isFocused может получить значение, но если пользователь размывается от ввода, что произойдет с этим значением? Он будет не синхронизирован. Кроме того, как упоминалось в комментариях, autoFocus может конфликтовать с несколькими компонентами

Итак, как выбрать реквизит и методы?

В большинстве случаев реквизиты будут ответом. Методы можно использовать только в случаях "пожара и забывания", таких как scrollToBottom в чате, когда приходит новое сообщение, scrollIntoView и тому подобное. Это однократное поведение, которое магазин не заботится и пользователь может изменить с помощью взаимодействия, поэтому логическая поддержка не подходит. По всем остальным, я бы пошел с реквизитом.

Здесь jsbin:

http://jsbin.com/waholo/edit?html,js,output