【问题标题】:Detect click outside of component with React Native Web?使用 React Native Web 检测组件外部的点击?
【发布时间】:2020-06-18 02:15:23
【问题描述】:

我正在使用 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 不是函数

如果我登录ref.current,我可以看到没有contains 方法。这对于 React Native Web 是否存在?

【问题讨论】:

    标签: react-native-web


    【解决方案1】:

    注意:这仅适用于 react-native-web

    这里是演示:https://snack.expo.io/@nomi9995/5b60ae

    <View> 是自定义的基于类的 React 组件,因此它在 ref 中返回 React 组件实例。而且它没有任何特定于 DOM 的方法,例如 .contains

    您可以通过document.getElementsByClassName()[0]为查看和访问dom元素赋予唯一的className

    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",
      },
    });
    
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-27
    • 1970-01-01
    • 2017-12-16
    • 2019-06-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多