removeEventListener 不适用于模态关闭
removeEventListener doesn't work on Modal close
我正在构建一个使用语义 UI React 的 React 应用程序。我有一些缩略图可以打开模态组件以在模态中显示全尺寸图像。我还有用于浏览下一个和上一个的按钮。随着按钮的点击,我想使用箭头键进行导航。当模式打开时,我可以将事件侦听器添加到 window。但是当我关闭模式并打开另一个模式时,一个重复的事件侦听器添加到 window。这意味着我需要在模式关闭时删除事件侦听器。但是,Semantic UI React Modal 组件的 onClose 和 onUnmount 道具不应用删除。我怎样才能申请?除了 removeEventListener 之外的任何东西都可以 运行 在 onClose 或 onUnmount 中,但是 removeEventListener 不会 运行.
这是整个附件组件:
import React, { Fragment, useState } from 'react'
import { Button, Card, Modal, Image } from 'semantic-ui-react'
import parse from 'html-react-parser'
import { IMedia } from '../../app/models/media'
interface IProps {
attachedMedia: IMedia,
gallery: IMedia[],
featured: boolean
}
const Attachment: React.FC<IProps> = ({ attachedMedia, gallery, featured }) => {
const [open, setOpen] = useState(false)
const [index, setIndex] = useState(gallery.indexOf(attachedMedia))
const [disabledNext, setDisabledNext] = useState(false)
const [disabledPrev, setDisabledPrev] = useState(false)
const handlePrev = () => {
if (index > 0) {
setIndex(index - 1)
setDisabledNext(false)
if (index === 1) setDisabledPrev(true)
}
}
const handleNext = () => {
if (index < gallery.length - 1) {
setIndex(index + 1)
setDisabledPrev(false)
if (index === gallery.length - 2) setDisabledNext(true)
}
}
const handleClose = () => {
setIndex(gallery.indexOf(attachedMedia))
setDisabledPrev(false)
setDisabledNext(false)
setOpen(false)
window.removeEventListener('keydown', handleKeyPress)
}
const handleMount = () => {
if (index === 0) setDisabledPrev(true)
if (index === gallery.length - 1) setDisabledNext(true)
window.addEventListener('keydown', handleKeyPress)
}
const handleKeyPress = (e: KeyboardEvent) => {
console.log(e)
}
return (
<Fragment>
{featured ?
(attachedMedia.media_details.sizes.medium?.source_url !== undefined) ?
<Image src={attachedMedia.media_details.sizes.medium.source_url} ui={false} onClick={() => {setOpen(true)}} />
:
<Image src={attachedMedia.media_details.sizes.full.source_url} ui={false} onClick={() => {setOpen(true)}} />
:
<Card className="attachment"><Image src={attachedMedia.media_details.sizes.thumbnail.source_url} onClick={() => setOpen(true)} /></Card>
}
<Modal open={open} centered={false} onClose={handleClose} onMount={handleMount}>
<Modal.Header>
{parse(gallery[index].title.rendered)}
</Modal.Header>
<Modal.Content image scrolling>
<Image src={gallery[index].media_details.sizes.full.source_url} wrapped fluid />
<Modal.Description>
{parse(gallery[index].description.rendered)}
</Modal.Description>
</Modal.Content>
<Modal.Actions>
<Button disabled={disabledPrev} onClick={handlePrev}>Previous image</Button>
<Button disabled={disabledNext} onClick={handleNext}>Next image</Button>
</Modal.Actions>
</Modal>
</Fragment>
)
}
export default Attachment
此处,handleClose 函数包含 removeEventListener,但移除不适用于 window,尽管 handleClose 中的其余代码可以 运行 有效。
我能够 运行 removeEventListener 的唯一尝试是在 handleKeyPress 函数中使用它。但这不是我想要的,它会在一键按下后删除监听器。只要模式打开,我就希望能够按键。
如何在模式关闭时让 removeEventListener 生效?
您可以使用 useEffect
挂钩。
因此,您需要从 handleOpen
和 handleClose
常量中删除 add/remove eventListener。
示例:
React.useEffect(() => {
if (open) window.addEventListener('keydown', handleKeyPress);
else window.removeEventListener('keydown', handleKeyPress);
}, [open]
);
打开模式时,将 open
状态设置为 true。
这个effect
随着open
状态的改变而触发。
因此,当它打开时,您正在添加侦听器,而当它关闭时,您正在删除侦听器。
简单!
我从 中得出了一个解决方案。使用 useEffect 并删除清理函数中的事件侦听器为我提供了所需的结果。这是代码块:
useEffect(() => {
if (open) window.addEventListener('keydown', handleKeyPress)
return () => {
window.removeEventListener('keydown', handleKeyPress)
}
}, [open])
我正在构建一个使用语义 UI React 的 React 应用程序。我有一些缩略图可以打开模态组件以在模态中显示全尺寸图像。我还有用于浏览下一个和上一个的按钮。随着按钮的点击,我想使用箭头键进行导航。当模式打开时,我可以将事件侦听器添加到 window。但是当我关闭模式并打开另一个模式时,一个重复的事件侦听器添加到 window。这意味着我需要在模式关闭时删除事件侦听器。但是,Semantic UI React Modal 组件的 onClose 和 onUnmount 道具不应用删除。我怎样才能申请?除了 removeEventListener 之外的任何东西都可以 运行 在 onClose 或 onUnmount 中,但是 removeEventListener 不会 运行.
这是整个附件组件:
import React, { Fragment, useState } from 'react'
import { Button, Card, Modal, Image } from 'semantic-ui-react'
import parse from 'html-react-parser'
import { IMedia } from '../../app/models/media'
interface IProps {
attachedMedia: IMedia,
gallery: IMedia[],
featured: boolean
}
const Attachment: React.FC<IProps> = ({ attachedMedia, gallery, featured }) => {
const [open, setOpen] = useState(false)
const [index, setIndex] = useState(gallery.indexOf(attachedMedia))
const [disabledNext, setDisabledNext] = useState(false)
const [disabledPrev, setDisabledPrev] = useState(false)
const handlePrev = () => {
if (index > 0) {
setIndex(index - 1)
setDisabledNext(false)
if (index === 1) setDisabledPrev(true)
}
}
const handleNext = () => {
if (index < gallery.length - 1) {
setIndex(index + 1)
setDisabledPrev(false)
if (index === gallery.length - 2) setDisabledNext(true)
}
}
const handleClose = () => {
setIndex(gallery.indexOf(attachedMedia))
setDisabledPrev(false)
setDisabledNext(false)
setOpen(false)
window.removeEventListener('keydown', handleKeyPress)
}
const handleMount = () => {
if (index === 0) setDisabledPrev(true)
if (index === gallery.length - 1) setDisabledNext(true)
window.addEventListener('keydown', handleKeyPress)
}
const handleKeyPress = (e: KeyboardEvent) => {
console.log(e)
}
return (
<Fragment>
{featured ?
(attachedMedia.media_details.sizes.medium?.source_url !== undefined) ?
<Image src={attachedMedia.media_details.sizes.medium.source_url} ui={false} onClick={() => {setOpen(true)}} />
:
<Image src={attachedMedia.media_details.sizes.full.source_url} ui={false} onClick={() => {setOpen(true)}} />
:
<Card className="attachment"><Image src={attachedMedia.media_details.sizes.thumbnail.source_url} onClick={() => setOpen(true)} /></Card>
}
<Modal open={open} centered={false} onClose={handleClose} onMount={handleMount}>
<Modal.Header>
{parse(gallery[index].title.rendered)}
</Modal.Header>
<Modal.Content image scrolling>
<Image src={gallery[index].media_details.sizes.full.source_url} wrapped fluid />
<Modal.Description>
{parse(gallery[index].description.rendered)}
</Modal.Description>
</Modal.Content>
<Modal.Actions>
<Button disabled={disabledPrev} onClick={handlePrev}>Previous image</Button>
<Button disabled={disabledNext} onClick={handleNext}>Next image</Button>
</Modal.Actions>
</Modal>
</Fragment>
)
}
export default Attachment
此处,handleClose 函数包含 removeEventListener,但移除不适用于 window,尽管 handleClose 中的其余代码可以 运行 有效。
我能够 运行 removeEventListener 的唯一尝试是在 handleKeyPress 函数中使用它。但这不是我想要的,它会在一键按下后删除监听器。只要模式打开,我就希望能够按键。
如何在模式关闭时让 removeEventListener 生效?
您可以使用 useEffect
挂钩。
因此,您需要从 handleOpen
和 handleClose
常量中删除 add/remove eventListener。
示例:
React.useEffect(() => {
if (open) window.addEventListener('keydown', handleKeyPress);
else window.removeEventListener('keydown', handleKeyPress);
}, [open]
);
打开模式时,将 open
状态设置为 true。
这个effect
随着open
状态的改变而触发。
因此,当它打开时,您正在添加侦听器,而当它关闭时,您正在删除侦听器。
简单!
我从
useEffect(() => {
if (open) window.addEventListener('keydown', handleKeyPress)
return () => {
window.removeEventListener('keydown', handleKeyPress)
}
}, [open])