我正在尝试创建一个弹出订阅框,只要单击关闭按钮或单击弹出窗口之外的任何位置,该框就会关闭。我创建了一个模态组件和一个状态
showModal
,用于切换该模态的可见性。我尝试将 setShowModal(false)
添加到外部 div
元素,但这只会禁用整个模式。每当我们在模态之外单击时,可以做什么来关闭模态。这就是我的主页的样子
const [showModal, setShowModal] = useState(false);
return (
<>
<div
className="homepage"
style={{
filter: showModal ? "blur(8px)" : "none",
minHeight:"80vh",
}}
>
<section
className="homepage-hero"
style={{ paddingBottom:"-2rem", minHeight:"100vh" }}
>
<div className="hero-body">
<div className="container">
<div className="columns">
<div className="column ">
<h1>
<span className="heading">
Finance <br />
Scheme
</span>
<br />
</h1>
<p>
Lorem Ipsum
</p>
<div className="is-hidden-tablet">
</div>
<div className="button-group">
<button
style={{
fontWeight: "600",
padding: "0.75em 1.9em",
borderRadius: "0px",
color: "white",
backgroundColor: "#24ca7a",
border: "1px solid #24ca7a",
cursor: "pointer",
}}
onClick={() => setShowModal(true)}
>
Download
</button>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
{showModal && (
<Modal
modalId="signup-modal"
onClose={() => setShowModal(false)}
canDismiss={false}
modalWidth="70%"
style={{position:"fixed", top:"20", minHeight:"50vh"}}
>
<div className="contact-us" style={{ margin:"20px"}}>
<section className="contact-form" >
<div className="container">
<div className="columns is-8 ">
<div
className="column is-half-desktop is-full-mobile container-content"
style={{ boxShadow: "none" }}
>
{submitted ? (
<div className="success">
<img src={confirmedIllus} alt="" />
<h2>Your details have been submitted successfully!</h2>
</div>
) : (
<form onSubmit={handleOnSubmit} id="contact-form" >
<h1 className="heading" style={{ fontSize: "2rem" }}>
Your Details
</h1>
<br />
<div className="field">
<label className="label">Name</label>
<div className="control">
<input
className="input"
id="name"
value={name}
type="text"
placeholder="Your Full Name"
onChange={(e) => setName(e.target.value)}
required
/>
</div>
</div>
<div className="field">
<label className="label">Email</label>
<div className="control ">
<input
className={`input ${isDanger}`}
id="email"
value={email}
type="email"
onChange={handleOnChange}
placeholder="Your Email"
required
/>
{!validEmail && isDanger ? (
<span className="icon is-small is-right">
<i className="material-icons-round">warning</i>
</span>
) : (
" "
)}
</div>
{!validEmail && isDanger ? (
<p className="help is-danger">{emailMessage}</p>
) : (
""
)}
</div>
<div className="field is-grouped submit-button-group">
<div className="control">
<button
style={{
cursor: !validEmail ? "not-allowed" : "pointer",
}}
className="button submit-button"
id="submit-form"
>
Submit
</button>
</div>
</div>
</form>
)}
</div>
<div className="column is-half-desktop is-full-mobile " >
<img
src="/images/Ebook.svg"
className="is-hidden-mobile"
style={{ width: "70%", marginTop: "40%" }}
/>
<div className=" font-blue bottom-text">
Fill your details to download the free <b> Ebook </b>
</div>
</div>
</div>
</div>
</section>
</div>
</Modal>
)}
</>
);
您可以使用
useOnClickOutside
挂钩。该挂钩允许您检测指定元素之外的点击。
您必须导入以下内容
创建一个引用,将其添加到要检测外部点击的元素中
const ref = useRef();
我们的模式的状态
const [showModal, setShowModal] = useState(false);
调用钩子传入 ref 和在外部单击时调用的函数
useOnClickOutside(ref, () => setShowModal(false));
在此处渲染
返回(...);
//Hook
import { useEffect } from 'react';
export default function useOnClickOutside(ref, handler) {
useEffect(
() => {
const listener = (event) => {
// Do nothing if clicking ref's element or descendent elements
if (!ref.current || ref.current.contains(event.target)) {
return;
}
handler(event);
};
document.addEventListener("mousedown", listener);
document.addEventListener("touchstart", listener);
return () => {
document.removeEventListener("mousedown", listener);
document.removeEventListener("touchstart", listener);
};
},
// Add ref and handler to effect dependencies
// It's worth noting that because the passed-in handler is a new ...
// ... function on every render that will cause this effect ...
// ... callback/cleanup to run every render. It's not a big deal ...
// ... but to optimize you can wrap handler in useCallback before ...
// ... passing it into this hook.
[ref, handler]
);
}
在此处查看相关的 repl 输出 - https://spanishhotloaderprogram.thelovekesh.repl.co/
为此,您可以将
tabIndex=-1
赋予模态 div,然后可以使用 onBlur 事件。
const [showModal, setShowModal] = useState(false);
return (
<>
<div
className="homepage"
style={{
filter: showModal ? "blur(8px)" : "none",
minHeight:"80vh",
}}
>
<section
className="homepage-hero"
style={{ paddingBottom:"-2rem", minHeight:"100vh" }}
>
<div className="hero-body">
<div className="container">
<div className="columns">
<div className="column ">
<h1>
<span className="heading">
Finance <br />
Scheme
</span>
<br />
</h1>
<p>
Lorem Ipsum
</p>
<div className="is-hidden-tablet">
</div>
<div className="button-group">
<button
style={{
fontWeight: "600",
padding: "0.75em 1.9em",
borderRadius: "0px",
color: "white",
backgroundColor: "#24ca7a",
border: "1px solid #24ca7a",
cursor: "pointer",
}}
onClick={() => setShowModal(true)}
>
Download
</button>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
{showModal && (
<Modal
modalId="signup-modal"
onBlur={() => setShowModal(false)}
canDismiss={false}
modalWidth="70%"
style={{position:"fixed", top:"20", minHeight:"50vh"}}
tabIndex={-1}
>
<div className="contact-us" style={{ margin:"20px"}}>
<section className="contact-form" >
<div className="container">
<div className="columns is-8 ">
<div
className="column is-half-desktop is-full-mobile container-content"
style={{ boxShadow: "none" }}
>
{submitted ? (
<div className="success">
<img src={confirmedIllus} alt="" />
<h2>Your details have been submitted successfully!</h2>
</div>
) : (
<form onSubmit={handleOnSubmit} id="contact-form" >
<h1 className="heading" style={{ fontSize: "2rem" }}>
Your Details
</h1>
<br />
<div className="field">
<label className="label">Name</label>
<div className="control">
<input
className="input"
id="name"
value={name}
type="text"
placeholder="Your Full Name"
onChange={(e) => setName(e.target.value)}
required
/>
</div>
</div>
<div className="field">
<label className="label">Email</label>
<div className="control ">
<input
className={`input ${isDanger}`}
id="email"
value={email}
type="email"
onChange={handleOnChange}
placeholder="Your Email"
required
/>
{!validEmail && isDanger ? (
<span className="icon is-small is-right">
<i className="material-icons-round">warning</i>
</span>
) : (
" "
)}
</div>
{!validEmail && isDanger ? (
<p className="help is-danger">{emailMessage}</p>
) : (
""
)}
</div>
<div className="field is-grouped submit-button-group">
<div className="control">
<button
style={{
cursor: !validEmail ? "not-allowed" : "pointer",
}}
className="button submit-button"
id="submit-form"
>
Submit
</button>
</div>
</div>
</form>
)}
</div>
<div className="column is-half-desktop is-full-mobile " >
<img
src="/images/Ebook.svg"
className="is-hidden-mobile"
style={{ width: "70%", marginTop: "40%" }}
/>
<div className=" font-blue bottom-text">
Fill your details to download the free <b> Ebook </b>
</div>
</div>
</div>
</div>
</section>
</div>
</Modal>
)}
</>
);
在 div className 主页中,单击时可以使用条件,如果 showModal 为 true --> setShowModal 为 false 就像
<div
className="homepage"
style={{
filter: showModal ? "blur(8px)" : "none",
minHeight: "80vh",
}}
onClick={() => showModal && setShowModal(false)}
>
https://www.youtube.com/watch?v=J5hGX5_XZDk&t=737s 从7.00开始关注这个视频,他在react 18中使用了 useRef 来切换模块的最佳方法