как реагировать на программный фокус

Я пытаюсь реализовать очень простой вариант использования, функцию пользовательского интерфейса, где:

  1. В нем есть ярлык с некоторым контентом
  2. Если щелкнуть, текстовый ввод заменяет его содержимым метки
  3. Пользователь может редактировать содержимое
  4. При нажатии кнопки ввод скрывается и метка возвращается с обновленным контентом

Я мог бы, наконец, все правильно (на самом деле с бэкэндом MongoBD, редуксом и т.д.), И единственное, что я никогда не мог сделать (полный день в поиске по Google и чтение подобных сообщений) был следующим:

Когда появится мой ввод текста, я не могу перенести на него фокус! Сначала я устал так:

<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 и SOF:

this.refs.updateTheWord.focus();

которые вместе с подобными предложениями все не сработали. Также я попытался обмануть Реакт, чтобы убедиться, что я могу что-то сделать! Я использовал реальный DOM:

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

и это тоже не сработало. Одна вещь, которую я даже не мог понять, чтобы выразить это, - это предложение вроде этого: имея ref как метод (я "догадываюсь"), я даже не пробовал его, потому что у меня есть кратность этих компонентов, и мне нужно ref для дальнейшего получения значения из, за компонент, и я не мог себе представить, если мой ref не назван, как я мог бы получить значение!

Так что, пожалуйста, дайте мне понять, помогая понять, что если я не использую форму (потому что мне нужен один блок ввода, заменяющий метку), как бы я мог сосредоточиться, когда класс CSS (Bootstrap) скрытый "пожалуйста?

Ответ 1

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

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>
    );
  }
}

Обновление
Начиная с Реакции 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>
    );
  }
}

Ответ 2

Просто добавьте атрибут автофокуса на input. (конечно в JSX это autoFocus)

<input autoFocus ...

Ответ 3

Используйте метод componentDidUpdate чтобы каждый раз обновлять компонент

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

Ответ 4

крючок useFocus

// 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>
        </>
    )

}

Для более полной демонстрации [нажмите здесь] [1].

Ответ 5

Найдите пример здесь с помощью React Hooks: https://codepen.io/googol7/pen/MdrGaR

const { useEffect } = React

const setFocus = () => {
    this.textInput.focus()
}

function App() {
    // Similar to componentDidMount and componentDidUpdate:
    useEffect(() => {
        setFocus()
    })

    return <div>
        <button onClick={setFocus} className="btn btn-primary">
            Set focus
        </button>
        <input ref={elem => (this.textInput = elem)} placeholder="Focus on me" />
    </div>
}

Ответ 6

В дополнение к предыдущим ответам я добавил 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 обработчик к любому элементу