在React中单击组件外部时更改状态

时间:2018-02-07 22:21:43

标签: javascript reactjs components

我有一个下拉列表,如下图所示: enter image description here

当我单击文件夹图标时,它会打开并关闭,因为showingProjectSelector属性处于设置为false的状态。

  constructor (props) {
    super(props)
    const { organization, owner, ownerAvatar } = props
    this.state = {
      owner,
      ownerAvatar,
      showingProjectSelector: false
    }
  }

当我点击图标时,它会正确打开和关闭。

<i
  onClick={() => this.setState({ showingProjectSelector: !this.state.showingProjectSelector })}
  className='fa fa-folder-open'>
</i>

但是我要做的是在我点击外面时关闭下拉列表。如何在不使用任何库的情况下执行此操作?

这是整个组件:https://jsbin.com/cunakejufa/edit?js,output

4 个答案:

答案 0 :(得分:3)

您可以尝试利用onBlur

<i onClick={...} onBlur={() => this.setState({showingProjectSelector: false})}/>

答案 1 :(得分:1)

我遇到了同样的问题。阅读后解决了这个问题: Detect click outside React component 请尝试:

答案 2 :(得分:0)

您应该使用高阶组件来包装您想听其外部点击的组件。

此组件示例只有一个道具:“ onClickedOutside”,它接收一个函数。

ClickedOutside.js
import React, { Component } from "react";

export default class ClickedOutside extends Component {
  componentDidMount() {
    document.addEventListener("mousedown", this.handleClickOutside);
  }

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

  handleClickOutside = event => {
    // IF exists the Ref of the wrapped component AND his dom children doesnt have the clicked component 
    if (this.wrapperRef && !this.wrapperRef.contains(event.target)) {
      // A props callback for the ClikedClickedOutside
      this.props.onClickedOutside();
    }
  };

  render() {
    // In this piece of code I'm trying to get to the first not functional component
    // Because it wouldn't work if use a functional component (like <Fade/> from react-reveal)
    let firstNotFunctionalComponent = this.props.children;
    while (typeof firstNotFunctionalComponent.type === "function") {
      firstNotFunctionalComponent = firstNotFunctionalComponent.props.children;
    }

    // Here I'm cloning the element because I have to pass a new prop, the "reference" 
    const children = React.cloneElement(firstNotFunctionalComponent, {
      ref: node => {
        this.wrapperRef = node;
      },
      // Keeping all the old props with the new element
      ...firstNotFunctionalComponent.props
    });

    return <React.Fragment>{children}</React.Fragment>;
  }
}

答案 3 :(得分:0)

如果要使用此功能已经存在的很小的组件(466字节压缩),则可以签出该库react-outclick

关于库的好处是它还使您可以检测组件外部和组件内部的点击。它还支持检测其他类型的事件。

使用该库,您可以在组件内部拥有类似的内容。

import OnOutsiceClick from 'react-outclick';

class MyComp extends Component { 

  render() {
    return (
      <OnOutsiceClick
        onOutsideClick={() => this.setState({showingProjectSelector: false})}>
        <Dropdown />
      </OnOutsiceClick>
    );
  }
}