我希望制作一个高阶组件来管理外部点击。当确定用户已经点击给定组件外部时,应该执行某个传递的功能。该HOC有两个参数:
此 ClickOutside 组件如下所示:
import React from 'react'
const { Component } = React
import { findDOMNode } from 'react-dom'
export default function ClickOutside (BoundaryComponent, onOutsideClick) {
return class Wrapper extends Component {
constructor (props) {
super(props)
}
componentDidMount() {
document.addEventListener('click', this.handleClick.bind(this), true)
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClick.bind(this), true)
}
render () {
const props = Object.assign({}, this.props, { ref: this.getContainer.bind(this) })
return (
<BoundaryComponent
{...props}
/>
)
}
getContainer (wrapped) {
this.container = findDOMNode(wrapped)
}
handleClick(e) {
if (this.container && !this.container.contains(e.target) && typeof onOutsideClick === 'function') {
onOutsideClick()
}
}
}
}
我正试图像这样使用这个组件:
import React from 'react'
const { ClickOutside } = 'utils/click-outside'
import { updatePicklistActiveIndex } from 'components/store/actions'
import { getPicklistActiveIndex } from 'components/store/selectors'
import PickList from 'components/picklist'
// ...
function mapDispatchToProps (dispatch) {
return {
updatePicklistActiveIndex: (activeIndex) => { dispatch(updatePicklistActiveIndex(activeIndex)) },
}
}
function mapStateToProps (state) {
return {
picklistActiveIndex: getPicklistActiveIndex(state),
}
}
let onOutsideClick = null // This feels like a code smell
class DropdownPickList extends PickList {
constructor(props) {
super(props)
this.state = {
dropdownVisible: false,
}
onOutsideClick = () => {
this.props.updatePicklistActiveIndex(-1)
this.setState({ dropdownVisible: false })
}
}
// ...
render() {
return (
//...jsx to render DropdownPickList
)
}
}
const pickList = ClickOutside(DropdownPickList, () => { onOutsideClick() })
export default connect(mapStateToProps, mapDispatchToProps)(pickList)
上述实施正如我所料......
但是在DropdownPickList类的上下文之外定义onOutsideClick
,然后在这个类的构造函数中覆盖这个变量引用只是感觉不对。但它似乎是获取关闭下拉列表所需的类中的道具和状态的唯一方法。
我还尝试在DropdownPickList类中使用静态方法来处理onOutsideClick,但是这个问题是这个类作为一个未呈现的组件传递,所以我无法访问我的handleClick中的任何实例方法HOC。
必须有更好的方法吗?任何帮助或替代实施的想法/模式将不胜感激!
答案 0 :(得分:1)
不是创建函数,只需导出包装器并按以下方式更改:
BoundaryComponent:移动到包装器的子节点(所以它实际上是一个包装器),如下所示:
<Wrapper>
<BoundaryComponent />
<Wrapper>
在内部包装器中,您将呈现{this.props.children}
onOutsideClick:onOutsideClick函数移动到Wrapper
的道具:
<Wrapper onOutsideClick={this.onOutsideClick}>
<BoundaryComponent />
<Wrapper>