消失的DOM元素没有注册点击事件

Disappearing DOM element does not register click event

我正在 React 中构建一个输入字段,如下所示:

单击'x'时(StyledCloseCircle),文本将被清除,'x'符号应该消失。 '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. 单击 'x' 时的操作顺序是什么,导致它注册 mousedown 而不是 click
  2. 我怎样才能达到预期的效果?

您应该创建一个单独的状态来控制 show/hide 清除按钮的位置。像现在一样显示它 onFocus,但如果用户在输入容器外单击或单击“清除”按钮,则隐藏它。您还可以隐藏它 onBlur 但有一些超时 (500-1000ms) 以防用户使用键盘而不是鼠标。

这是以下代码的 CodeSnadbox example

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