React中如何在点击BODY时分发Action以隐藏错误通知?
解决React中点击文档任意位置无法隐藏错误通知的问题
你的代码核心问题是闭包陷阱:
useEffect的依赖项是空数组[],导致它仅在组件首次渲染时执行一次,绑定的是当时创建的hideNote函数。hideNote内部引用的style是组件初始渲染时的空值,后续即使通知显示使style更新,该函数仍会使用旧的style值,导致if (style)判断不成立,无法触发dispatch隐藏通知。
方案一:用useCallback稳定函数引用
通过useCallback包裹hideNote,确保函数引用在依赖项不变时保持稳定,同时更新useEffect的依赖列表:
import { useContext, useEffect, useCallback } from 'react'; const Layout = ({ children }) => { const [{ note: { style, text } }, dispatch] = useContext(StoreContext) const hideNote = useCallback(() => { dispatch(setNote({ style: ``, text: `` })) }, [dispatch]) useEffect(() => { document.body.addEventListener(`click`, hideNote) return function cleanup() { document.body.removeEventListener(`click`, hideNote) } }, [hideNote]) return ( <> <Note style={style} text={text} /> <Navigation /> {children} <Footer /> </> ); } export default Layout
方案二:在useEffect内部定义事件处理函数
将hideNote直接定义在useEffect内部,依赖style和dispatch,确保每次style变化时,事件处理函数能获取最新状态:
const Layout = ({ children }) => { const [{ note: { style, text } }, dispatch] = useContext(StoreContext) useEffect(() => { const hideNote = () => { if (style) { dispatch(setNote({ style: ``, text: `` })) } } document.body.addEventListener(`click`, hideNote) return function cleanup() { document.body.removeEventListener(`click`, hideNote) } }, [style, dispatch]) return ( <> <Note style={style} text={text} /> <Navigation /> {children} <Footer /> </> ); } export default Layout
额外注意事项
如果Note组件内部的点击事件调用了event.stopPropagation(),会阻止事件冒泡到body,导致点击通知本身无法触发隐藏逻辑。若需要点击通知也能隐藏,需确保Note组件不阻止事件冒泡。
内容的提问来源于stack exchange,提问作者Nastro
相关产品推荐
相关产品推荐

