在@headlessui/react中如何将Popover的open属性传递给父组件
@headlessui/react Popover 开合状态自定义监听实现方案
方案1:非受控模式(无需手动维护open状态,推荐)
不需要修改Popover默认的开合逻辑,直接利用组件内部暴露的open状态监听变化即可,代码最简洁:
import { Popover } from '@headlessui/react' import { useEffect } from 'react' function CustomPopover() { // 自定义开合回调 const handleOpenStateChange = (isOpen: boolean) => { if (isOpen) { // 弹窗打开时的自定义逻辑,比如埋点上报、拉取数据 console.log('弹窗已打开') } else { // 弹窗关闭时的自定义逻辑,比如重置表单、清空缓存 console.log('弹窗已关闭') } } return ( <Popover> {/* Popover 内置render props会返回当前的open状态 */} {({ open }) => { useEffect(() => { handleOpenStateChange(open) }, [open]) return ( <> <Popover.Button>触发按钮</Popover.Button> <Popover.Panel> 弹窗自定义内容 </Popover.Panel> </> ) }} </Popover> ) }
方案2:受控模式(需要将open状态暴露给外层封装组件)
如果你需要把open状态传到组件外层使用,可以用受控模式绑定状态,完全保留默认的点击外部关闭、ESC关闭等原生行为:
import { Popover } from '@headlessui/react' import { useState, useEffect } from 'react' // 封装后的Popover组件 function WrappedPopover(props: { onOpenChange: (isOpen: boolean) => void }) { // 外层维护开合状态 const [isPopoverOpen, setIsPopoverOpen] = useState(false) // 监听状态变化执行自定义操作 useEffect(() => { props.onOpenChange(isPopoverOpen) }, [isPopoverOpen, props.onOpenChange]) return ( {/* 绑定open和onChange属性,同步内部状态 */} <Popover open={isPopoverOpen} onChange={setIsPopoverOpen} > <Popover.Button>触发按钮</Popover.Button> <Popover.Panel> 弹窗自定义内容 <Popover.Button>关闭按钮</Popover.Button> </Popover.Panel> </Popover> ) } // 外层调用示例 function App() { return ( <WrappedPopover onOpenChange={(isOpen) => { // 外层执行自定义逻辑 console.log('弹窗状态变化:', isOpen) }} /> ) }
注意事项
- 受控模式下必须同时传入
open和onChange两个属性,否则默认的关闭行为会失效 - 没有外层使用open状态的需求时优先选择方案1,不需要额外维护状态,避免逻辑冗余
内容的提问来源于stack exchange,提问作者Lin Kassem
相关产品推荐
相关产品推荐

