Запретить установку фокуса onClick, если на входе уже есть фокус в ReactJS

#reactjs #material-ui

Вопрос:

ReactJS/Материал-вопрос новичка в пользовательском интерфейсе. У меня есть функциональный компонент, который использует эффект и крючки. Для простоты я создал приведенный ниже пример кода. Если вы нажмете в любом месте в пределах границы контейнера автозаполнения (обозначенного красной рамкой), он установит фокус на поле ввода. Но если вы снова нажмете на границу, вы заметите, что она снова установит фокус. Я пытаюсь установить фокус только на поле ввода, если фокус на поле ввода еще не установлен, не прибегая к использованию document.activeElement и избегая анти-шаблонов. Я в настоящее время использую useRef, но не уверен, нужно ли мне использовать useEffect, useState или я могу каким-то образом просто использовать компонент автозаполнения, проверив, виден ли список опций или нет. Мы будем очень признательны за любую помощь. Ссылка на песочницу https://codesandbox.io/s/solitary-fog-2t7p4?file=/src/demo.js

Пример кода

 import React from "react";
import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";

export default function ComboBox() {
  const container = React.useRef();
  const input = React.useRef();

  return (
    <>
      <div
        ref={container}
        style={{ padding: 30, border: "1px solid red" }}
        onClick={() => {
          if (!input.current.focused) {
            input.current.focus();
          }
        }}
      >
        <Autocomplete
          options={top100Films}
          getOptionLabel={(option) => option.title}
          openOnFocus
          selectOnFocus
          style={{ width: 300 }}
          renderInput={(params) => (
            <TextField
              inputRef={input}
              {...params}
              label="Combo box"
              variant="outlined"
            />
          )}
        />
      </div>
    </>
  );
}

// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
const top100Films = [
  { title: "The Shawshank Redemption", year: 1994 },
  { title: "The Godfather", year: 1972 },
  { title: "The Godfather: Part II", year: 1974 },
  { title: "The Dark Knight", year: 2008 },
  { title: "12 Angry Men", year: 1957 }];
 

Ответ №1:

mousedown вместо этого используйте событие

 onMouseDown={(event) => {
  event.preventDefault();
  input.current.focus();
}}
 

Не знаете, как справиться с этим на мобильном устройстве, попробуйте это touchstart событие.

Комментарии:

1. Огромное спасибо! Это сделало свое дело. Простое решение. Я слишком много думал об этом, так как не был уверен, нужно ли это использовать или использовать эффект. Я еще не решил, буду ли я сохранять эту функциональность на мобильных устройствах или нет, поэтому на данный момент меня не волнует, работает она или не работает на мобильных устройствах. Еще раз спасибо!