如何制作组件引用并听取外部点击?

时间:2019-05-10 08:26:54

标签: javascript reactjs

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

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

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未捕获的TypeError:_this.dropdownBoxRef.contains不是函数

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

2 个答案:

答案 0 :(得分: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)行是改变游戏规则的人。

答案 1 :(得分:0)

引用具有存储在名为current的属性中的内容。因此,要真正达到您的元素,您必须执行this.dropdownBoxRef.current并在其上调用.contains