使用 React Native Web 检测组件外部的点击?
Detect click outside of component with React Native Web?
我正在使用 React Native Web。我需要检测用户何时在组件外部单击。这仅在网络上加载,因此不必在本机上运行。
我一直在尝试使用这个钩子的一个版本:
https://usehooks.com/useOnClickOutside/
在我的组件中:
useOnClickOutside(ref, () => setIsOpen(false));
中钩:
function useOnClickOutside(ref, handler) {
React.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);
};
},
[ref, handler],
);
}
这给我一个错误:
TypeError: ref.current.contains is not a function
如果我登录 ref.current
我可以看到没有 contains
方法。这是否适用于 React Native Web?
注意: 这仅适用于 react-native-web
这里是演示:https://snack.expo.io/@nomi9995/5b60ae
<View>
是基于 class 的自定义 React 组件,因此它 returns React 组件实例在 ref.而且它没有任何 DOM-specific 方法,如 .contains
您可以通过 document.getElementsByClassName()[0]
为查看和访问 dom 元素提供唯一的 class 名称
import React, { useState, useEffect, useRef } from "react";
import { StyleSheet, Text, View, Button } from "react-native";
function useOnClickOutside(ref, handler) {
useEffect(() => {
const listener = (event) => {
if (!ref.current || document.getElementsByClassName("uniqueClassName")[0].contains(event.target)) {
return;
}
handler(event);
};
document.addEventListener("mousedown", listener);
document.addEventListener("touchstart", listener);
return () => {
document.removeEventListener("mousedown", listener);
document.removeEventListener("touchstart", listener);
};
}, [ref, handler]);
}
export default function App() {
const ref = useRef();
const [isModalOpen, setModalOpen] = useState(false);
useOnClickOutside(ref, () => setModalOpen(false));
return (
<View style={styles.container}>
{isModalOpen ? (
<View ref={ref} style={styles.modalBox} className="uniqueClassName">
<Text style={{ color: "#FFFFFF" }}>this is modalBox</Text>
</View>
) : (
<Button onPress={() => setModalOpen(true)} title="Open Modal" />
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "red",
alignItems: "center",
justifyContent: "center",
},
modalBox: {
backgroundColor: "blue",
height: 200,
width: 200,
justifyContent: "center",
alignItems: "center",
},
});
我正在使用 React Native Web。我需要检测用户何时在组件外部单击。这仅在网络上加载,因此不必在本机上运行。
我一直在尝试使用这个钩子的一个版本: https://usehooks.com/useOnClickOutside/
在我的组件中:
useOnClickOutside(ref, () => setIsOpen(false));
中钩:
function useOnClickOutside(ref, handler) {
React.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);
};
},
[ref, handler],
);
}
这给我一个错误:
TypeError: ref.current.contains is not a function
如果我登录 ref.current
我可以看到没有 contains
方法。这是否适用于 React Native Web?
注意: 这仅适用于 react-native-web
这里是演示:https://snack.expo.io/@nomi9995/5b60ae
<View>
是基于 class 的自定义 React 组件,因此它 returns React 组件实例在 ref.而且它没有任何 DOM-specific 方法,如 .contains
您可以通过 document.getElementsByClassName()[0]
import React, { useState, useEffect, useRef } from "react";
import { StyleSheet, Text, View, Button } from "react-native";
function useOnClickOutside(ref, handler) {
useEffect(() => {
const listener = (event) => {
if (!ref.current || document.getElementsByClassName("uniqueClassName")[0].contains(event.target)) {
return;
}
handler(event);
};
document.addEventListener("mousedown", listener);
document.addEventListener("touchstart", listener);
return () => {
document.removeEventListener("mousedown", listener);
document.removeEventListener("touchstart", listener);
};
}, [ref, handler]);
}
export default function App() {
const ref = useRef();
const [isModalOpen, setModalOpen] = useState(false);
useOnClickOutside(ref, () => setModalOpen(false));
return (
<View style={styles.container}>
{isModalOpen ? (
<View ref={ref} style={styles.modalBox} className="uniqueClassName">
<Text style={{ color: "#FFFFFF" }}>this is modalBox</Text>
</View>
) : (
<Button onPress={() => setModalOpen(true)} title="Open Modal" />
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "red",
alignItems: "center",
justifyContent: "center",
},
modalBox: {
backgroundColor: "blue",
height: 200,
width: 200,
justifyContent: "center",
alignItems: "center",
},
});