Реагировать на список элементов фокуса в дочернем компоненте после действия другого дочернего компонента

РЕДАКТИРОВАТЬ: Хотя ответ Сун Кима верен для исходного сценария, я забыл добавить, что это поведение (выбор следующего элемента из списка) может быть переключено другим ключом, например ArrowDown, и в этом случае tabIndex не будет по крайней мере на начальном этапе.

`` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `

Я пытаюсь работать над раскрывающимся компонентом, который имеет два отдельных (родственных) функциональных компонента. Первый - это обычный <input>, который принимает значение. Второй - <ul>, который отображает результаты.

Поток заключается в том, что изначально отображается только <input>, когда вы вводите и получаете результаты обратно из базы данных, затем отображается <ul>.

Вышеупомянутые функции выполнены, однако сейчас я хочу добиться того, чтобы, когда я закончил печатать (потому что я доволен результатами, которые вижу), я нажимаю tab, затем первый элемент в списке результатов (именно <a> внутри <li>) фокусируется, а затем, если я продолжаю нажимать tab, фокусируется следующий элемент на последнем и так далее, пока не дойдет до последнего элемента.

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

Я думал о самом чистом подходе, чтобы заставить это работать. Я подумал, что, возможно, использование ref через createRef и forwardRed могло бы быть хорошей идеей, но, честно говоря, я пока не могу осмыслить это, поэтому я решил обратиться за помощью.

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

Родительский компонент:

class Parent extends React.Component {
  componentDidMount() {}

  handleInternalKeyPress = (e) => {
    if (e.key === 'Tab') {
      e.preventDefault()
      // do something?
    }
  }

  render() {
    return (
      <section>
        <section>
          <DropdownInput
            handleTextChange = {this.props.handleTextChange}
            handleKeyDown = {this.handleInternalKeyPress}
          />
          <DropdownResults
            results = {this.props.results}
            handleKeyDown = {this.handleInternalKeyPress}
          />
        </section>
      </section>
    )
  }
}

Входной компонент:

const DropdownInput = props => (
  <Input
    onChange = {e => props.handleTextChange(e)}
    onKeyDown = {e => props.handleKeyDown(e)}
    type = "text"
  />
)

Компонент результатов (<ul>):

// Maybe this should be a React.forwardRef() instead of
// an arrow function, but I'm not sure if this is the
// best/most elegant approach
const DropdownResults = props => (
  <ul>
    {props.results.map((result, i) => (
      <li key = {result.resultIdKey}>
        <a
          // perhaps a ref should go in here?
          onKeyDown = {e => props.handleKeyDown(e)}
          role = "link"
          tabIndex = {i}
        >
          {result.resultTitleDisplayKey}
        </a>
      </li>
    ))}
  </ul>
)

Опять же, компоненты немного сложнее, но это основная идея того, как они работают.

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

Я немного подумал, но этот действительно меня поразил, особенно потому, что я хочу придерживаться лучших / последних практик React, поэтому любая помощь, которая может быть предоставлена, будет очень благодарна!

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
2
0
2 452
1

Ответы 1

Я никогда не использовал tabIndex, но поиграл после прочтения некоторых статей.

Похоже, что настройка tabIndex = {0} работала вместо увеличения с помощью i.

const DropdownResults = props => (
  <ul>
    {props.results.map((result, i) => (
      <li key = {result.resultIdKey}>
        <a
          // perhaps a ref should go in here?
          onKeyDown = {e => props.handleKeyDown(e)}
          role = "link"
          tabIndex = {0}
        >
          {result.resultTitleDisplayKey}
        </a>
      </li>
    ))}
  </ul>
);

demo

По какой-то причине в документации Google (Использование tabindex) говорится, что использование tabIndex больше 0 является анти-шаблоном без особых объяснений (как и этот более старая запись в блоге, который не объясняет, почему и то и другое)

хотя Документация MDN ничего не говорит о том, что использование tabIndex больше 0 является анти-шаблоном.

Но пока установка всех значений tabIndex=0, похоже, работает.

Вы можете форк кода.
Edit 002pz9kp20

Привет, большое спасибо за быстрый ответ! Не могли бы вы взглянуть на правку исходного сообщения? Это полностью решило собственное поведение вкладок, но как насчет использования других клавиш для вкладки, таких как стрелка вниз. Спасибо!

deathandtaxes 15.11.2018 23:03

@deathandtaxes Вы имеете в виду, что хотите иметь возможность переходить к разным элементам с помощью «клавиш со стрелками» в качестве альтернативы? (Вот так я понял обновленный вопрос) ...

dance2die 15.11.2018 23:14

Да, точно. Я не думаю, что это будет слишком сложно, если будет выбран первый элемент в списке. Однако я застрял в том, как сфокусировать этот первый элемент, когда вы закончили вводить ввод и нажали «ArrowDown» (с помощью клавиш со стрелками).

deathandtaxes 15.11.2018 23:17

@deathandtaxes Я обновил песочницу, используя forwardRef, чтобы передать список ссылок детям, чтобы вы могли выбирать, используя как вкладки, так и клавиши со стрелками. Это, кстати, выглядит довольно некрасиво, хотя и работает ... Потребовались бы серьезные рефакторинги.

dance2die 16.11.2018 04:54

Другие вопросы по теме