如何封装监听Escape键关闭模态框的useEffect实现跨组件复用?
当然可以封装,这正是React自定义Hook的用武之地
你可以把这段监听Escape键关闭模态框的逻辑封装成一个可复用的自定义Hook,这样在任何需要的组件里直接调用就行,不用重复写相同的代码。
第一步:创建自定义Hook
新建一个文件(比如useEscapeToClose.ts),把逻辑移进去:
import { useEffect } from 'react'; // 接收控制模态框显示状态的setter函数 const useEscapeToClose = (setIsOpen: (value: boolean) => void) => { useEffect(() => { const handleEscapeKey = (e: KeyboardEvent) => { if (e.key === 'Escape') { setIsOpen(false); } }; document.addEventListener('keydown', handleEscapeKey); // 组件卸载时移除监听,避免内存泄漏 return () => { document.removeEventListener('keydown', handleEscapeKey); }; }, [setIsOpen]); }; export default useEscapeToClose;
第二步:在组件中复用
在需要的组件里导入这个Hook,直接传入对应的set函数即可:
import useEscapeToClose from './useEscapeToClose'; import { useProfileModal } from './your-modal-hooks'; const ProfileComponent = () => { const [shouldShowModal, setShouldShowModal] = useProfileModal(); // 一行代码搞定监听逻辑 useEscapeToClose(setShouldShowModal); return ( <> <button onClick={() => setShouldShowModal(true)}>打开模态框</button> {shouldShowModal && <div className="modal">模态框内容</div>} </> ); };
进阶优化:仅在模态框打开时监听
如果想进一步优化,可以让Hook只在模态框处于打开状态时才绑定事件,减少不必要的性能消耗:
import { useEffect } from 'react'; // 新增isOpen参数,判断是否需要监听 const useEscapeToClose = (isOpen: boolean, setIsOpen: (value: boolean) => void) => { useEffect(() => { // 模态框没打开时直接返回,不绑定事件 if (!isOpen) return; const handleEscapeKey = (e: KeyboardEvent) => { if (e.key === 'Escape') { setIsOpen(false); } }; document.addEventListener('keydown', handleEscapeKey); return () => { document.removeEventListener('keydown', handleEscapeKey); }; }, [isOpen, setIsOpen]); };
组件中调用时传入模态框的显示状态:
useEscapeToClose(shouldShowModal, setShouldShowModal);
内容的提问来源于stack exchange,提问作者Ryan Roberts
相关产品推荐
相关产品推荐

