当点击其他元素/身体失败时,反应切换并关闭

时间:2018-04-30 11:45:38

标签: javascript reactjs javascript-events

我想在用户点击某个元素时触发展开状态,但是当用户使用ref点击外部时我无法实现关闭元素。

这部分出了点问题

handleClick = e => {
    if (this.node.contains(e.target)) {
      this.setState({
        expand: !this.state.expand // doesn't work?
      },()=>console.log(this.state.expand));

      return;
    }

    this.handleClickOutside();
  };

控制台触发了两次。

https://codesandbox.io/s/71l34po56x

如果您只是将句柄中的expand状态更改为true,您可以看到几乎可以工作的结果,但我怎样才能实现2件事。

  1. 用户可以切换内容。
  2. 用户点击了内容将关闭的内容或处理程序的外部。

2 个答案:

答案 0 :(得分:1)

问题是您将同一事件处理程序this->两次附加到handleClick(一次在div函数中,也在render中)。

这就是为什么当你点击componentWillMount时,你将状态设置两次,结果div从false变为true,然后从true变为false。

答案 1 :(得分:0)

您可以完全发出componentWillMount()和componentWillUnmount函数。然后当在div上进行单击时,切换功能可以完美地工作。你在这里缺少的是,当在div之外进行点击时,clickhandler()不再附加到这个div,而是它被点击的根div。

为了解决这个问题,我添加了一个父div来占用最大高度,然后使用点击处理程序展开并切换div值。

以下是代码段。

import React, { Component } from "react";
import { render } from "react-dom";

const styles = {
  fontFamily: "sans-serif",
  textAlign: "center",
  border: "2px solid red",
  height: "500px"
};

const styles2 = {
  fontFamily: "sans-serif",
  textAlign: "center",
  border: "2px solid black"
};

export default class App extends Component {
  state = {
    expand: false
  };

  expandedArea() {
    return <div>content area</div>;
  }

  handleClickOutside = () => {
    this.setState({
      expand: false
    });
  };

  handleClick = e => {
    console.log("ddd");
    e.stopPropagation();
    if (this.node.contains(e.target)) {
      this.setState({
        expand: !this.state.expand // doesn't work?
      });

      return;
    }

    this.handleClickOutside();
  };

  render() {
    const { expand } = this.state;

    return (
      <div style={styles} onClick={e => this.handleClickOutside(e)}>
        <div
          style={styles2}
          ref={node => (this.node = node)}
          onClick={e => this.handleClick(e)}
        >
          hello world
          {expand && this.expandedArea()}
        </div>
      </div>
    );
  }
}

render(<App />, document.getElementById("root"));

希望这对你所看到的内容有所帮助,谢谢!