【问题标题】:How to make ref to component and listen for click outside?如何对组件进行引用并监听外部点击?
【发布时间】:2019-05-10 16:41:49
【问题描述】:

所以我正在尝试制作下拉选项组件。我想通过单击按钮来显示它,如果在此组件之外检测到单击,则将其隐藏。

这是一个代码。我做了参考,但我不明白如何检查点击是否在组件上:

import React, { Component } from 'react'
import './OptionsMenu.sass'

import DropdownBox from '../DropdownBox/DropdownBox'
import Icon from '../Icon/Icon'

class OptionsMenu extends Component {
    constructor(){
        super()
        this.dropdownBoxRef = React.createRef()
    }

  handleClickOutside = event => {
    if (this.dropdownBoxRef && !this.dropdownBoxRef.contains(event.target)) {
      this.props.close()
    }
  }

  componentDidMount() {
    document.addEventListener('mousedown', this.handleClickOutside)
  }

  componentWillUnmount() {
    document.removeEventListener('mousedown', this.handleClickOutside)
  }

  render() {
    const options = this.props.options.map(option => (
      <li className='OptionsList-Element'>
        <div className='OptionsList-ElementIcon'>
          <Icon name={option.icon} />
        </div>
        <span>{option.label}</span>
      </li>
    ))
    return (
      <DropdownBox ref={this.dropdownBoxRef} styles={this.props.styles}>
        <ul className='OptionsList'>{options}</ul>
      </DropdownBox>
    )
  }
}

export default OptionsMenu

使用此代码我有错误: OptionsMenu.js:14 Uncaught TypeError: _this.dropdownBoxRef.contains 不是函数

我知道错误,因为它没有 .contains()。那么我必须尝试使用​​什么?

【问题讨论】:

  • 您介意提供DropdownBox 组件的代码吗?
  • 您的Dropdown 需要一个isVisible 状态

标签: javascript reactjs


【解决方案1】:

请找到有助于解决您的问题的更新代码:

import ReactDOM from "react-dom";

import "./styles.css";
import React, { Component } from "react";

class OptionsMenu extends Component {
  constructor() {
    super();
    this.dropdownBoxRef = React.createRef();
  }

  handleClickOutside = event => {
    if (this.dropdownBoxRef && !this.dropdownBoxRef.current.contains(event.target)) {
      this.props.close();
    }
  };

  componentDidMount() {
    document.addEventListener("mousedown", this.handleClickOutside);
  }

  componentWillUnmount() {
    document.removeEventListener("mousedown", this.handleClickOutside);
  }

  render() {
    const options = ["a", "b", "c"].map(option => (
      <li className="OptionsList-Element">
        <div className="OptionsList-ElementIcon">Icon</div>
        <span>{option.label}</span>
      </li>
    ));
    return (
      <div ref={this.dropdownBoxRef} styles={this.props.styles}>
        <ul className="OptionsList">{options}</ul>
      </div>
    );
  }
}

export default OptionsMenu;

const rootElement = document.getElementById("root");
ReactDOM.render(<OptionsMenu />, rootElement);

注意:this.dropdownBoxRef.current.contains(event.target) 行改变了游戏规则。

【讨论】:

  • 感谢您的解决方案!我认为这会有所帮助,但现在我有不同的问题。我有这个警告Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?,那是因为我的下拉框组件可以正常工作。你能帮助解决问题,而不是切换到基于类的
  • @WhoIsDT:尝试将功能组件(DropdownBox)更改为类组件。我希望它能解决你的问题。
  • @WhoIsDT 尝试将 div 包装在您的功能组件上,并将 ref 从功能组件移动到包装器 div。
【解决方案2】:

Refs 将内容存储在名为current 的属性中。因此,为了真正接触到您的元素,您必须执行 this.dropdownBoxRef.current 并为此调用 .contains

【讨论】:

    猜你喜欢
    • 2014-07-12
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多