我似乎无法使用组件将卸载可靠地删除侦听器
I can’t seem to reliably remove a listener using componentWillUnmount
我在窗口中添加了一个侦听器来检测onClickOutside
类型的场景(具体来说,在菜单外部单击时折叠菜单(。这是包含相关代码的组件:
import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import LinkedStateMixin from 'react-addons-linked-state-mixin';
import styles from './DescriptiveSelect.css';
import classNames from 'classnames';
import _ from 'underscore';
export default class DescriptiveSelect extends Component {
static propTypes = {
attrForOptionLabel: PropTypes.string,
attrForOptionValue: PropTypes.string,
children: PropTypes.string,
className: PropTypes.string,
disabled: PropTypes.bool,
nullLabel: PropTypes.string,
onUpdate: PropTypes.func,
options: PropTypes.array,
selectedLabel: PropTypes.string,
selectedOption: PropTypes.number,
valueLink: PropTypes.object
}
mixins: [LinkedStateMixin]
static defaultProps = {
attrForOptionLabel: 'name',
attrForOptionValue: 'id',
disabled: false,
selectedOption: 0,
selectedLabel: 'Select one…'
}
state = {
isOpen: false,
options: []
}
componentDidMount() {
this.buildOptions(this.props.options);
window.addEventListener('click', this.onDocumentClick.bind(this));
}
componentWillUnmount() {
window.removeEventListener('click', this.onDocumentClick);
}
onDocumentClick(event) {
const theLabel = ReactDOM.findDOMNode(this);
if (theLabel && theLabel.contains(event.target)) {
this.setState({isOpen: !this.state.isOpen});
} else {
this.setState({isOpen: false});
}
event.preventDefault();
}
handleSelection(option) {
if (this.props.onUpdate) {
this.props.onUpdate(option.id);
}
this.setState({'isOpen': false});
}
/**
* Build out <select> menu options
* Data must be formatted with the following attributes:
* const theData = [
* {
* id: 1,
* sequence: 0,
* short_name: 'App'
* }
* ];
* @param {array} data The data to convert, either from an endpoint
* response or passed in via the `options` prop.
*/
buildOptions(data) {
const _this = this;
const results = data;
const resultLength = results.length;
const {
attrForOptionValue,
attrForOptionLabel
} = this.props;
// Sort data by sequence attribute
_.sortBy(results, 'sequence');
// Cycle through JSON results and create <option> elements
for (let i = 0; i < resultLength; i++) {
const option = results[i];
_this.state.options.push(
<option key={option.id} value={option[attrForOptionValue]}>{option[attrForOptionLabel]}</option>
);
_this.forceUpdate();
}
}
render() {
const {
className,
nullLabel,
options
} = this.props;
// Classes for select menu
const selectClasses = classNames({
[styles.LabelWrapper]: true,
[className]: className
});
/**
* Contents of the custom select.
* Taken from the `options` prop that should be passed in.
*/
const optionNodes = options.map((option) => {
return (
<li className={styles.Option} key={option.id} onClick={this.handleSelection.bind(this, option)}>
<div className={styles.OptionLabel}>a <strong>{option.name}</strong></div>
<div className={styles.OptionDetail}>{option.description}</div>
</li>
);
});
return (
<label className={selectClasses} ref="theLabel">
<select
className={styles.Select}
nullLabel={nullLabel}
options={options}
ref="theSelect"
valueLink={this.props.valueLink}
>
{ nullLabel ? <option value="">{nullLabel}</option> : null }
{ this.state.options }
</select>
{ this.state.isOpen ? <div className={styles.Menu}>
<ul className={styles.OptionsWrapper}>
{optionNodes}
</ul>
<footer className={styles.Footer}>
<p><a href="#">Learn more</a> about App.typography titles.</p>
</footer>
</div> : null }
</label>
);
}
}
我不确定为什么,但它实际上并没有删除侦听器,所以我最终在控制台中得到了其中几个:
未捕获的错误:不变冲突:在 已卸载的组件。
此代码中是否有任何可能导致问题的明显内容?
您正在尝试删除未绑定的函数。 .bind
返回一个新函数,即 this.onDocumentClick.bind(this) !== this.onDocumentClick
.
您应该在构造函数中绑定该方法一次,然后在整个过程中使用该方法:
constructor(props) {
super(props);
this.onDocumentClick = this.onDocumentClick.bind(this);
// use this.onDocumentClick everywhere
}
相关文章:
- 加载侦听器上的函数触发得太早
- 在 <对象> 标记中加载 SVG 时,将侦听器添加到 SVG 卸载事件
- 事件侦听器更新就绪在加载时未显示确认,而更新实际存在
- 自动加载面板侦听器扩展
- 用于在页面上加载图像的 JavaScript 事件侦听器
- 在 Ajax 加载后更新侦听器的最佳实践
- 当事件侦听器作为部分页面的一部分加载时,如何将事件侦听器添加到窗体中
- 仅在侦听器函数中加载脚本/模块会导致问题吗?
- 如何在 Extjs4 中使用加载侦听器
- jquery文档就绪侦听器与图像加载;执行顺序
- 添加焦点侦听器而不是加载
- jQuery和Django表单验证重新加载并提交事件侦听器
- React:从服务器卸载事件侦听器
- 元素必须可见才能“加载”事件侦听器才能工作
- Greasemonkey弹出循环未等待加载事件侦听器
- 我似乎无法使用组件将卸载可靠地删除侦听器
- 在循环中加载多个图像并为每个图像添加侦听器
- 如何向页面加载时没有立即显示的元素添加事件侦听器?
- 在DOM内容加载后附加元素中的事件侦听器
- 卸载React时删除事件侦听器