React JS - фокус элемента на вводе не работает

У меня проблемы с фокусировкой элемента программно. У меня есть ul, который выглядит так:

      <ul className="text-left">
        {Object.keys(props.characters).map((char, i) => {
          return (
            <li key={props.characters[char].key}>
              <button type="button" className={"btn align-middle bg_" + props.characters[char].character}>
                <div className={"label text-left float-left " + getFontColorFromCharacter(props.characters[char].character)}>
                  <img alt="" className="char-img" src={"/images/characters/" + props.characters[char].character + "_xs.png"}/>
                  <input className="align-middle d-none" id={props.characters[char].key + "_input"} type="text" placeholder="Nom joueur" value={props.characters[char].player_name} onChange={e => props.changePlayerNameHandler(props.characters[char],e)} onBlur={e => toggleDNone(props.characters[char].key)} onKeyDown={e => tabToNext(e)}/>
                  <span className="align-middle" id={props.characters[char].key + "_span"} onClick={e => toggleDNone(props.characters[char].key)} > {props.characters[char].player_name}</span>
                </div>
                <div className={"actions " + getFontColorFromCharacter(props.characters[char].character)}>
                  <span className="action">
                    <FontAwesomeIcon icon="times-circle" title="Supprimer" onClick={() => props.removeCharacterHandler(props.characters[char].key)}/>
                  </span>
                </div>
              </button>
            </li>
          );
        })}
      </ul>

Javascript:

//Toggle d-none class on input & span for player name edition
function toggleDNone(key) {
    document.getElementById(key + "_input").classList.toggle("d-none");
    document.getElementById(key + "_span").classList.toggle("d-none");

    if (!document.getElementById(key + "_input").classList.contains("d-none")) {
        document.getElementById(key + "_input").focus();
    }
}

//When the user hit tab key, navigate to next input
function tabToNext(event){
    if(event.key === "Tab")
    {
        var allInput = document.querySelectorAll("[id$='_input']");

        var indexOfCurrent = Array.from(allInput).indexOf(event.target);
        var id;
        if (indexOfCurrent + 1 === Array.from(allInput).length)
        {
            id = allInput[0].id;
        }
        else
        {
            id = allInput[indexOfCurrent + 1].id;
        }

        toggleDNone(allInput[indexOfCurrent].id.replace("_input", ""));
        toggleDNone(id.replace("_input",""));
    }
}

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

Я попытался установить для tabIndex значение -1, как я видел в сообщении, но это не сработало.

Любые идеи?


person AnthonyDa    schedule 09.01.2019    source источник
comment
Можете ли вы показать нам свой полный компонент React?   -  person Treycos    schedule 09.01.2019
comment
Я отредактировал вопрос ;) Полный компонент слишком велик, чтобы помещать его здесь.   -  person AnthonyDa    schedule 09.01.2019
comment
Почему бы вам не использовать обработчик onFocus?   -  person gazdagergo    schedule 09.01.2019
comment
Я не хочу что-то делать, когда элемент находится в фокусе, я просто хочу установить фокус на элементе.   -  person AnthonyDa    schedule 09.01.2019
comment
Можете ли вы объяснить, почему у вас для начала есть комбинация span/input? Это, безусловно, может быть достигнуто более простым способом.   -  person Mario Nikolaus    schedule 09.01.2019
comment
Это просто эстетика, я не хотел, чтобы ввод отображался все время.   -  person AnthonyDa    schedule 09.01.2019
comment
Не делайте этого, увеличивая дерево DOM и выполняя антипаттерны HTML... Просто стилизуйте ввод по своему вкусу в зависимости от состояния фокуса... Вы можете отключить внешний вид по умолчанию с помощью свойства внешнего вида css...   -  person Mario Nikolaus    schedule 09.01.2019
comment
Спасибо, Марио, я оптимизирую это, когда закончу все основные функции ^^   -  person AnthonyDa    schedule 09.01.2019


Ответы (1)


Решение найдено. Проблема заключалась в том, что второй вызов toggleDNone начался до завершения первого.

Я только что добавил setTimeOut 100 мс при втором вызове, и это сработало.

Спасибо всем

person AnthonyDa    schedule 09.01.2019