Вызов window.addEventListener
внутри useEffect
вызывается, когда React рендерит компонент, что происходит на focus . Событие, которое вызывает фокус, это не щелчок, а mousedown
. Когда происходит следующее mouseup
, генерируется событие щелчка, которое перехватывается. Обратите внимание, что если вы вкладываете вкладку в фокус ввода, это не вызывает ошибку.
Существует несколько подходов, чтобы исправить это, но я рекомендую игнорировать события щелчка, которые происходят на самом входе.
Вот пример: я добавил ссылку в <input>
, передал ее в OutsideWrapper
и добавил проверку, как у вас, для wrapperRef
для новой ссылки.
function Test() {
const [down, setDown] = React.useState(false);
const focusRef = React.useRef();
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>
<input ref={focusRef} onFocus={() => setDown(true)} />
{down && (
<OutsideWrapper
onOutside={() => setDown(false)}
focusedRef={focusRef}
className="input-wrapper"
>
children
</OutsideWrapper>
)}
</h2>
</div>
);
}
const OutsideWrapper = ({ children, onOutside, className, focusedRef }) => {
const wrapperRef = React.useRef(null);
const [style, setStyles] = React.useState({
opacity: 1
});
React.useEffect(() => {
console.log("1. component was mounted");
const i = e => {
console.log(e.target, wrapperRef.current);
if (
wrapperRef.current &&
!wrapperRef.current.contains(e.target) &&
focusedRef.current !== e.target
) {
console.log("3. outside click was trigerred");
e.preventDefault();
setStyles({ opacity: 0 });
setTimeout(() => {
onOutside();
}, 100);
}
};
window.addEventListener("click", i, true);
console.log("2. listener was added");
return () => {
console.log("4. listerner was removed");
window.removeEventListener("click", i, true);
};
}, [onOutside, focusedRef]);
return (
<div
ref={wrapperRef}
style={style}
className={`outside-wrapper ${className}`}
>
{children}
</div>
);
};