Skip to content

useDismiss

当请求关闭时关闭浮动元素 - 默认情况下,当用户按下 escape 键或用指针在浮动元素外部时。

¥Closes the floating element when a dismissal is requested — by default, when the user presses the escape key or outside of the floating element with their pointer.

import {useDismiss} from '@floating-ui/react';

这对于确保用户完成与浮动元素的交互(包括键盘支持)时关闭浮动元素非常有用。

¥This is useful to ensure the floating element is closed when the user is finished interacting with it, including keyboard support.

用法

¥Usage

该 Hook 返回事件处理程序 props。

¥This Hook returns event handler props.

要使用它,请将 useFloating() 返回的 context 对象传递给它,然后将其结果输入 useInteractions() 数组。然后将返回的 prop getter 传播到元素上进行渲染。

¥To use it, pass it the context object returned from useFloating(), and then feed its result into the useInteractions() array. The returned prop getters are then spread onto the elements for rendering.

function App() {
  const [isOpen, setIsOpen] = useState(false);
 
  const {refs, floatingStyles, context} = useFloating({
    open: isOpen,
    onOpenChange: setIsOpen,
  });
 
  const dismiss = useDismiss(context);
 
  const {getReferenceProps, getFloatingProps} = useInteractions([
    dismiss,
  ]);
 
  return (
    <>
      <div ref={refs.setReference} {...getReferenceProps()}>
        Reference element
      </div>
      {isOpen && (
        <div
          ref={refs.setFloating}
          style={floatingStyles}
          {...getFloatingProps()}
        >
          Floating element
        </div>
      )}
    </>
  );
}

属性

¥Props

interface UseDismissProps {
  enabled?: boolean;
  escapeKey?: boolean;
  referencePress?: boolean;
  referencePressEvent?: 'pointerdown' | 'mousedown' | 'click';
  outsidePress?: boolean | ((event: MouseEvent) => boolean);
  outsidePressEvent?: 'pointerdown' | 'mousedown' | 'click';
  ancestorScroll?: boolean;
  bubbles?:
    | boolean
    | {escapeKey?: boolean; outsidePress?: boolean};
  capture?:
    | boolean
    | {escapeKey?: boolean; outsidePress?: boolean};
}

enabled

默认:true

¥default: true

有条件地启用/禁用 Hook。

¥Conditionally enable/disable the Hook.

useDismiss(context, {
  enabled: false,
});

escapeKey

默认:true

¥default: true

esc 键后是否消除浮动元素。

¥Whether to dismiss the floating element upon pressing the esc key.

useDismiss(context, {
  escapeKey: false,
});

referencePress

默认:false

¥default: false

是否在按下参考元素时消除浮动元素。

¥Whether to dismiss the floating element upon pressing the reference element.

useDismiss(context, {
  referencePress: true,
});

你可能需要确保 useHover() 钩子中的 move 选项在使用时已被禁用。

¥You likely want to ensure the move option in the useHover() hook has been disabled when this is in use.

键盘按下退出

¥Keyboard press dismissal

如果你想确保通过键盘在 “pressing” 参考元素上也消除浮动元素,你可以为此添加自己的处理程序。

¥If you’d like to ensure the floating element is also dismissed upon “pressing” the reference element via the keyboard, you can add in your own handler(s) for this.

getReferenceProps({
  // for a native <button>
  onClick() {
    setOpen(false);
  },
});

referencePressEvent

默认:'pointerdown'

¥default: 'pointerdown'

用于确定 “press” 的事件类型。

¥The type of event to use to determine a “press”.

useDismiss(context, {
  // Eager on both mouse + touch input.
  referencePressEvent: 'pointerdown',
  // Eager on mouse input; lazy on touch input.
  referencePressEvent: 'mousedown',
  // Lazy on both mouse + touch input.
  referencePressEvent: 'click',
});

outsidePress

默认:true

¥default: true

是否在按下浮动元素和参考元素外部时关闭浮动元素。

¥Whether to dismiss the floating element upon pressing outside of both the floating and reference elements.

useDismiss(context, {
  outsidePress: false,
});

如果你有另一个元素(例如吐司),它在浮动元素的 React 树之外渲染,并且不希望浮动元素在按下时关闭,你可以像这样保护检查:

¥If you have another element, like a toast, that is rendered outside the floating element’s React tree and don’t want the floating element to close when pressing it, you can guard the check like so:

useDismiss(context, {
  // Same as `true`, but with a custom guard check.
  outsidePress: (event) => !event.target.closest('.toast'),
});
function App() {
  // The toast is not inside the Dialog's React tree, so we
  // need to add a guard to consider it a child of the Dialog
  // to prevent the Dialog's outside press from closing it.
  return (
    <>
      <Dialog />
      <Toast className="toast" />
    </>
  );
}

outsidePressEvent

默认:'pointerdown'

¥default: 'pointerdown'

用于确定 “press” 的事件类型。

¥The type of event to use to determine a “press”.

useDismiss(context, {
  // Eager on both mouse + touch input.
  outsidePressEvent: 'pointerdown',
  // Eager on mouse input; lazy on touch input.
  outsidePressEvent: 'mousedown',
  // Lazy on both mouse + touch input.
  outsidePressEvent: 'click',
});

ancestorScroll

默认:false

¥default: false

是否在滚动溢出祖级时消除浮动元素。

¥Whether to dismiss the floating element upon scrolling an overflow ancestor.

useDismiss(context, {
  ancestorScroll: true,
});

bubbles

默认:undefined

¥default: undefined

确定事件监听器是否向上冒泡通过浮动元素树。

¥Determines whether event listeners bubble upwards through a tree of floating elements.

  • escapeKey 确定按下 esc 键是否会冒泡,从而导致祖级浮动元素也消失。例如,如果你使用 esc 键关闭对话框内的工具提示,你可能不希望对话框也关闭,直到按下第二个键(这是默认行为)。

    ¥escapeKey determines whether pressing the esc key bubbles, causing ancestor floating elements to dismiss as well. For instance, if you’re dismissing a tooltip inside a dialog using the esc key, you likely don’t want the dialog to dismiss as well until a second key press, which is the default behavior.

  • outsidePress 确定按下子浮动元素外部是否会冒泡,从而导致祖级浮动元素也消失。将此设置为 false 需要设置 FloatingTree

    ¥outsidePress determines whether pressing outside of a child floating element bubbles, causing ancestor floating elements to dismiss as well. Setting this to false requires a FloatingTree to be set up.

useDismiss(context, {
  // Configure bubbling for all relevant events:
  bubbles: false,
  // Or, individually configure by event:
  bubbles: {
    escapeKey: true, // false by default
    outsidePress: false, // true by default
  },
});

capture

默认:undefined

¥default: undefined

确定是否使用捕获阶段事件监听器。

¥Determines whether to use capture phase event listeners.

useDismiss(context, {
  // Configure capturing for all relevant events:
  capture: true,
  // Or, individually configure by event:
  capture: {
    escapeKey: true, // false by default
    outsidePress: false, // true by default
  },
});

对关闭做出反应

¥Reacting to dismissal

要对退出事件做出反应,你可以在 onOpenChange 回调中检查 reason 字符串:

¥To react to the dismissal event, you can check for the reason string in the onOpenChange callback:

useFloating({
  open: isOpen,
  onOpenChange(nextOpen, event, reason) {
    setIsOpen(nextOpen);
 
    // Other ones include 'reference-press' and 'ancestor-scroll'
    // if enabled.
    if (reason === 'escape-key' || reason === 'outside-press') {
      console.log('Dismissed');
    }
  },
});

故障排除

¥Troubleshooting

在 iframe 中单击时未关闭

¥Does not close when clicking in an iframe

你可以使用 FloatingOverlay 组件,它将 “cover” iframe 确保在与浮动元素相同的文档中捕获点击,因为点击发生在覆盖背景上。这可确保 “外部媒体” 检测有效。

¥You can use the FloatingOverlay component which will “cover” iframes to ensure clicks are captured in the same document as the floating element, as the click occurs on the overlay backdrop. This guarantees “outside press” detection will work.