Исчезающий элемент DOM не регистрирует событие нажатия - PullRequest
1 голос
/ 21 марта 2019

Я создаю поле ввода в React, которое выглядит следующим образом:

Search box

Когда нажимается 'x' (StyledCloseCircle)текст будет очищен, а символ «х» должен исчезнуть.Символ 'x' в настоящее время отображается с javascript, когда поле ввода сфокусировано,

export const Search = React.forwardRef((props, ref) => {
  const [isFocused, setFocus] = useState(false);
  const [isHovered, setHover] = useState(false);

  return (
    <InputContainer
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
    >
      <StyledInput
        onFocus={() => setFocus(true)}
        onBlur={() => setFocus(false)}
        isHovered={isHovered}
        ref={ref}
        {...props}
      />
      {isFocused && !props.value && (
        <StyledMagnifyingGlass
          isHovered={isHovered}
          isFocused={isFocused}
          onClick={props.onSearch}
        />
      )}
      {isFocused && props.value && (
        <StyledCloseCircle onClick={() => console.log("THIS DOES NOT FIRE")} />
      )}
      {!isFocused && (
        <StyledMagnifyingGlass
          isHovered={isHovered}
          isFocused={isFocused}
          onClick={props.onSearch}
        />
      )}
    </InputContainer>
  );
});

Проблема заключается в том, что при нажатии на кнопку x ввод теряет фокус, что приводит к тому, что xудаляется при следующем рендеринге и не регистрирует событие click.Однако он вызывает событие mousedown.

Поэтому у меня два вопроса:

  1. Каков порядок операций при нажатии на «х», который приводитэто для регистрации mousedown но не click?
  2. Как мне добиться желаемого поведения?

1 Ответ

1 голос
/ 31 марта 2019

Вы должны создать отдельное состояние, чтобы контролировать, где показывать / скрывать кнопку «Очистить».Покажите его onFocus, как вы это делаете сейчас, но скройте его, если пользователь щелкает за пределами контейнера ввода или нажимает кнопку «Очистить».Вы можете дополнительно скрыть его onBlur, но с некоторым таймаутом (500-1000 мс) в случае, если пользователь использует клавиатуру вместо мыши.

Это пример CodeSnadbox кода ниже:

function App() {
  const inputContainerRef = useRef();
  const [value, setValue] = useState("");
  const [showClear, setShowClear] = useState(false);

  const onFocus = useCallback(() => {
    setShowClear(true);
  }, []);

  const onClear = useCallback(() => {
    setValue("");
    setShowClear(false);
  }, []);

  const onOutsideClick = useCallback(e => {
    // hide Clear button only if clicked outside of the container
    if (!inputContainerRef.current.contains(e.target)) {
      setShowClear(false);
    }
  }, []);

  useLayoutEffect(
    () => {
      // set the listener only if we shown the Clear button and remove the listener once we hid it
      if (showClear) {
        document.addEventListener("click", onOutsideClick);
        return () => document.removeEventListener("click", onOutsideClick);
      }
    },
    [showClear] // re-invoke if the state changes
  );

  return (
    <div className="App">
      <div className="input-container" ref={inputContainerRef}>
        <input
          value={value}
          onChange={e => {
            setValue(e.target.value);
          }}
          className="input"
          type="tetxt"
          onFocus={onFocus}
        />
        {showClear && (
          <div className="clear" onClick={onClear}>
            X
          </div>
        )}
      </div>
    </div>
  );
}
...