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. a标签中的javascript:;是什么

    a标签中的javascript:;是什么 一.问题 <a>标签中href="javascript:;"表示什么意思?? <a id="jsPswEdit ...

  2. elasticsearch index 之 create index(-)

    从本篇开始,就进入了Index的核心代码部分.这里首先分析一下索引的创建过程.elasticsearch中的索引是多个分片的集合,它只是逻辑上的索引,并不具备实际的索引功能,所有对数据的操作最终还是由 ...

  3. Raid阵列之简单介绍

    1.raid分类 软raid:用软件模拟raid芯片 硬raid:集成的后来添加的 2.raid基本简介 (1)raid是由廉价磁盘冗余阵列发展成为独立磁盘冗余阵列 (2)linux是借助MD(Mui ...

  4. Linux下MySQL允许远程连接以及授权命令

    --针对某个库做授权 GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'%' IDENTIFIED BY 'mypassword' WITH GRANT OPTION; ...

  5. Onvif开发之服务端成功对接Rtsp视频流篇

    前面篇介绍onvif服务端的发现功能,继续在之前的代码基础上完成一个RTSP流的工作,也就是客户端通过ONVIF协议来预览设备端在这个之前必须确定几个简单的条件1 设备端能被发现2 设备端支持RTSP ...

  6. 为root账户更名

    为root账户更名 处于安全考虑许多管理员想把root更名,具体方法如下: 1.先以root登陆系统 2.用vi 编辑/etc/passwd文件,将第一行的第一个root修改为你想要的账户名,然后保存 ...

  7. Android 关于::app:clean :app:preBuild UP-TO-DATE :app:preDebugBuild UP-TO-DATE,引用jar冲突问题

    错误提示: Information:Gradle tasks [:app:clean, :app:generateDebugSources, :app:generateDebugAndroidTest ...

  8. pycharm做什么

    pycharm做什么 说实话.作为一个Coder.每天在各种IDE中切换编写Code.如果一个IDE Look and Feel总是无形中影响你每天Code Farm的心情.那该是多么不爽的事情.特别 ...

  9. 【2017 Multi-University Training Contest - Team 5】Rikka with Graph

    [Link]:http://acm.hdu.edu.cn/showproblem.php?pid=6090 [Description] 给你n个点; 让你在这n个点上最多连m条无向边; 使得 ∑ni= ...

  10. android 自己定义View之SubmitView

    转载请注明出处:王亟亟的大牛之路 近期看了一大堆的自己定义View多数都能够充当耗时操作的交互界面.再接再厉再传一个SubmitView.一个和可用于模仿提交等待与用户交互用的一个自己定义View 效 ...