У меня проблема с компонентом React.js Dialog
, который содержит список элементов. Также есть оверлей в Dialog
. Он закрывается автоматически, когда пользователь нажимает на него. Но сценарий другой. Диалог также включает в себя список элементов, некоторые внешние ссылки которых обернуты вокруг элемента <a>
, а некоторые - с <div>
.
Но метод закрытия диалога работает некорректно. Диалог автоматически закрывается, когда я щелкаю внутри любого элемента списка.
Пожалуйста, посмотрите это:
Моя цель заключалась в том, чтобы закрыть диалоговое окно всякий раз, когда пользователь нажимал на оверлей или всякий раз, когда пользователь нажимал на элемент списка, заключенный в элемент <a>
. В противном случае закрывать его не следует.
Я все еще не могу понять, как правильно решить эту проблему?
App.js
import React, { useState } from 'react';
import Dialog from './Dialog';
import './App.css';
const App = () => {
const [isOpen, setIsOpen] = useState(false);
const onClickHandler = (isFalse) => {
if (!isFalse) {
setIsOpen(false);
} else {
setIsOpen(!isOpen);
}
};
return (
<div>
<button type="button" onClick={onClickHandler}>
Open Dialog
</button>
<Dialog isOpen={isOpen} onClick={onClickHandler} />
</div>
);
};
export default App;
Dialog.js
import React from 'react';
const Dialog = (props) => {
const { isOpen, onClick } = props;
const onCloseHandle = () => {
onClick(false);
};
return (
<div
className={isOpen ? 'dialog-wrap open' : 'dialog-wrap'}
onClick={onCloseHandle}
>
<div className="dialog">
<ul className="dialog-list">
<li>
<a
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
React.js
</a>
</li>
<li>
<a
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Another Link
</a>
</li>
<li>
<div>Should Not Close onClick</div>
</li>
<li>
<div>Should Not Close onClick</div>
</li>
</ul>
</div>
</div>
);
};
export default Dialog;
< Сильный > App.css
*,:before,:after {
box-sizing: border-box;
}
.dialog-wrap.open {
display: flex;
}
.dialog-wrap {
display: none;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 999;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
padding: 16px;
background-color: rgba(0,0,0,0.66);
}
@media (min-width: 640px) {
.dialog-wrap {
padding: 48px 32px;
}
}
@media (min-width: 1024px) {
.dialog-wrap {
padding-left: 40px;
padding-right: 40px;
}
}
.dialog {
position: relative;
margin: auto;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.1);
box-shadow: 0 12px 16px rgba(0, 0, 0, 0.08);
border-radius: 4px;
width: 500px;
}
.dialog-list {
margin-bottom: 0;
padding-left: 0;
color: #333;
list-style: none;
}
.dialog-list > li {
border-bottom: 1px solid #eee;
padding: 24px;
}
.dialog-list > li > a {
color: #333;
display: block;
text-decoration: none;
}
.dialog-list > li > div {
cursor: pointer;
}
2 ответа
В этой ситуации я бы создал элемент .dialog-background
и дал бы ему onCloseHandle
.
Я также добавляю свои элементы a
в опору onCloseHandle
as onClick
Если вы не хотите менять свое дерево реакций, вы можете решить это из следующего события:
<div
className={isOpen ? "dialog-wrap open" : "dialog-wrap"}
onClick={(e) => {
if (!e.target.closest('.dialog') || e.target.closest('a')) {
onClick(false)
}
}}
/>
Я думаю, что ваше событие click распространяется вверх по элементам и запускает onCloseHandle
на вашем .dialog-wrap
.
Самым простым решением этой проблемы было бы использование Event.stopPropagation()
на <div className="dialog">
Например.
<div className="dialog" onClick={ e => e.stopPropagation() }>
(Технически React использует "синтетические события", но они по-прежнему включают параметр stopPropagation
пока он взаимодействует с внутри React)
Похожие вопросы
Новые вопросы
reactjs
React - это библиотека JavaScript для создания пользовательских интерфейсов. Он использует декларативную компонентную парадигму и стремится быть одновременно эффективным и гибким.