Ich möchte eine Higher Order Component erstellen, um externe Klicks zu verwalten. Wenn festgestellt wird, dass ein Benutzer außerhalb einer bestimmten Komponente geklickt hat, sollte eine bestimmte übergebene Funktion ausgeführt werden. Diese HOC dauert 2 Parameter:Reactive HOC, um Klicks außerhalb einer bestimmten Komponente zu behandeln
- BoundaryComponent: die Komponente wir bei der Bestimmung interessiert sind, wenn Klicks außerhalb davon
- onOutsideClick sind: eine Funktion auszuführen, wenn ein Klick außerhalb der Komponente auftritt
Diese ClickOutside Komponente wie folgt aussieht:
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()
}
}
}
}
Und ich versuche, diese Komponente wie folgt zu verwenden:
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)
Die obige Umsetzung funktioniert, wie ich erwarten würde ...
Aber die Definition onOutsideClick
außerhalb des Kontextes der DropdownPickList Klasse, und dann überschreiben Diese Variablenreferenz innerhalb des Konstruktors dieser Klasse fühlt sich einfach falsch an. Aber es scheint die einzige Möglichkeit zu sein, Zugriff auf die Requisiten und den Zustand innerhalb der Klasse zu erhalten, die benötigt werden, um das Dropdown zu schließen.
Ich habe auch versucht, eine statische Methode in der DropDownPickList-Klasse zu verwenden, um das OnOutsideClick zu behandeln, aber das Problem dabei ist, dass Klasse als eine nicht gerenderte Komponente übergeben wird, so habe ich keinen Zugriff auf eine der Instanzmethoden in meinem handleClick von der HOC.
Es muss einen besseren Weg geben, dies zu tun? Jede Hilfe oder alternative Implementierung Ideen/Muster würde sehr geschätzt werden!