Most of the time, your components respond to events that occur within the component tree by defining their own handler or by accepting a handler defined by a parent component via props. Sometimes, this isn't enough. In this lesson, we'll rely on lifecycle hooks and good old fashioned DOM events to update state in a React component in response to an event that occurs outside of the component tree.

class Menu extends React.Component {
constructor(props) {
super(props)
this.state = {
isVisible: false
}
this.handleClickOutside = this.handleClickOutside.bind(this)
this.toggleOptions = this.toggleOptions.bind(this)
this.handleClick = this.handleClick.bind(this)
}
componentDidMount() {
document.addEventListener('click', this.handleClickOutside)
} componentWillUnmount() {
document.removeEventListener('click', this.handleClickOutside)
} handleClickOutside(evt) {
if (!this.node.contains(evt.target)) {
this.setState({ isVisible: false })
}
} toggleOptions(evt) {
evt.preventDefault()
this.setState(state => ({ isVisible: !state.isVisible }))
} handleClick(choice, evt) {
evt.preventDefault()
this.props.handleMenuChoice(choice)
this.setState({ isVisible: false })
} render() {
return (
<div className="menu" ref={el => (this.node = el)}>
<a href="#" onClick={this.toggleOptions}>
Options
</a>
{this.state.isVisible
? <div className="menuContents">
<a href="#" onClick={this.handleClick.bind(null, 'one')}>
One
</a>
<a href="#" onClick={this.handleClick.bind(null, 'two')}>
Two
</a>
<a href="#" onClick={this.handleClick.bind(null, 'three')}>
Three
</a>
<a href="#" onClick={this.handleClick.bind(null, '')}>
Clear Selection
</a>
</div>
: null}
</div>
)
}
}

The most important thing is how to detect whether user click outside the menu or not.

To do that, we use 'ref':

<div className="menu" ref={el => (this.node = el)}>

We assign the elememt to vairable 'this.node'.

console log the node:

<div class="menu">
<a href="#">options</a>
</div>

When we click inside the menu, the 'evt.target' is the 'a' tag.

If we click outside the menu, then then 'evt.target' is the whole html tag.

Therefore, we can check:

if (!this.node.contains(evt.target)) {

[React] Close the menu component when click outside the menu的更多相关文章

  1. React.createClass和extends Component的区别

    React.createClass和extends Component的区别主要在于: 语法区别 propType 和 getDefaultProps 状态的区别 this区别 Mixins 语法区别 ...

  2. React Native 中的component 的生命周期

    React Native中的component跟Android中的activity,fragment等一样,存在生命周期,下面先给出component的生命周期图 getDefaultProps ob ...

  3. React 的 PureComponent Vs Component

    一.它们几乎完全相同,但是PureComponent通过prop和state的浅比较来实现shouldComponentUpdate,某些情况下可以用PureComponent提升性能 1.所谓浅比较 ...

  4. 【转】Pro Android学习笔记(三十):Menu(1):了解Menu

    目录(?)[-] 创建Menu MenuItem的属性itemId MenuItem的属性groupId MenuItem的属性orderId MenuItem的属性可选属性 Menu触发 onOpt ...

  5. [React Native] Create a component using ScrollView

    To show a list of unchanging data in React Native you can use the scroll view component. In this les ...

  6. [React] Write a stateful Component with the React useState Hook and TypeScript

    Here we refactor a React TypeScript class component to a function component with a useState hook and ...

  7. [React] Refactor a Class Component with React hooks to a Function

    We have a render prop based class component that allows us to make a GraphQL request with a given qu ...

  8. 关于React的Container&Presentational Component模型结构分析

    react.js javascript 3 之前翻译了两篇关于Container&Presentational Component模型的文章,一篇是基础的Container和Component ...

  9. [React Router v4] Use the React Router v4 Link Component for Navigation Between Routes

    If you’ve created several Routes within your application, you will also want to be able to navigate ...

随机推荐

  1. Cocos2d-x手机游戏开发与项目实践具体解释_随书代码

    Cocos2d-x手机游戏开发与项目实战具体解释_随书代码 作者:沈大海  因为原作者共享的资源为UTF-8字符编码.下载后解压在win下显示乱码或还出现文件不全问题,现完整整理,解决全部乱码问题,供 ...

  2. 使用bitmap处理海量数据

    bitmap是一个十分实用的结构.所谓的Bit-map就是用一个bit位来标记某个元素相应的Value, 而Key即是该元素.因为採用了Bit为单位来存储数据,因此在存储空间方面,能够大大节省.  适 ...

  3. Java Swing设置主窗体位置居中方法

    01.第一种方法 int windowWidth = frame.getWidth(); //获得窗体宽  int windowHeight = frame.getHeight(); //获得窗体高 ...

  4. 聊聊高并发(十八)理解AtomicXXX.lazySet方法

    看过java.util.concurrent.atomic包里面各个AtomicXXX类实现的同学应该见过lazySet方法.比方AtomicBoolean类的lazySet方法 public fin ...

  5. UVA 558 Wormholes 【SPFA 判负环】

    题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_proble ...

  6. java一个月日历

    项目须要,获取当天之后的30天.并提示星期几(周几),写了一个工具类 /** * 计算日期时间 * @author shijing * 2015年8月10日下午2:16:09 * @param dat ...

  7. QVBoxLayout移除控件之后没有消失

    想在QWidget里面动态的添加和删除控件,给QWidget设置了一个布局管理器QVBoxLayout,要删除控件可以 使用QVBoxLayout::removeWidget(QWidget *w)方 ...

  8. three.js 运行3D模型

    HTML  <!DOCTYPE html> <html style="height: 100%;"> <head> <title>m ...

  9. 在gridview里查找模板里的button控件

    这个问题,真是搞了我1天,这次记住他 第一种方法: protected void GridView1_RowCommand(object sender, GridViewCommandEventArg ...

  10. 关于Blocking IO,non-Blokcing IO,async IO的区别和理解

    来源:http://shmilyaw-hotmail-com.iteye.com/blog/1896683 概括来说,一个IO操作可以分为两个部分:发出请求.结果完成.如果从发出请求到结果返回,一直B ...