Reputation: 3880
I have an event listener that listens to clicks. If these clicks are outside of a given dom element, a certain function is called (in this case, handleClick
).
Right now, the function handleClick
is only called if the event target is not the one that has the this.setWrapper
ref.
I am wondering how I can prevent handleClick
from being called if I also happen to click on .boxTwo
.
Note, I want to do this not by adding a ref to the div of .boxTwo
, but by querying to DOM to identify any clicks that happen inside of the div that has the class name 'boxTwo'. Thanks!
class App extends React.Component {
constructor() {
super();
this.state = {onClick: false};
this.setWrapperRef = this.setWrapperRef.bind(this);
this.handleClick = this.handleClick.bind(this);
}
componentDidMount() {
document.addEventListener('mousedown', this.handleClick);
}
componentWillUnmount() {
document.removeEventListener('mousedown', this.handleClick);
}
setWrapperRef(node) {
this.wrapperRef = node;
}
handleClick(event) {
if (this.wrapperRef && !this.wrapperRef.contains(event.target)) {
this.setState({onClick: !this.state.onClick});
}
}
render() {
return (
<section>
<div className="boxOne" ref={this.setWrapperRef} />
<div className="boxTwo" />
<div>{this.state.onClick ? "On" : "Off"}</div>
</section>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
.boxOne {
height: 100px;
width: 100px;
background: pink;
}
.boxTwo {
margin: 30px;
height: 50px;
width: 70px;
border: solid black 2px;
background: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="app"></div>
Upvotes: 0
Views: 62
Reputation: 1009
event.target.className
does not equal boxTwo
, like this snippet below.boxOne
class.!event.target.className
A little extra, I would have done it this way for the sake of readability
handleClick(event) {
// The ones that don't trigger
const disabledTriggers = ['boxOne', 'boxTwo'];
// Ok if no class contained in our event classList are disabled
const ok = !disabledTriggers.some(c => event.target.classList && event.target.classList.contains(c))
if(ok) {
this.setState({onClick: !this.state.onClick});
}
}
And here's your snippet with the solution and the least modifications.
class App extends React.Component {
constructor() {
super();
this.state = {onClick: false};
this.setWrapperRef = this.setWrapperRef.bind(this);
this.handleClick = this.handleClick.bind(this);
}
componentDidMount() {
document.addEventListener('mousedown', this.handleClick);
}
componentWillUnmount() {
document.removeEventListener('mousedown', this.handleClick);
}
setWrapperRef(node) {
this.wrapperRef = node;
}
handleClick(event) {
if (event.target.className !== 'boxTwo' && this.wrapperRef && !this.wrapperRef.contains(event.target)) {
this.setState({onClick: !this.state.onClick});
}
}
render() {
return (
<section>
<div className="boxOne" ref={this.setWrapperRef} />
<div className="boxTwo" />
<div>{this.state.onClick ? "On" : "Off"}</div>
</section>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
.boxOne {
height: 100px;
width: 100px;
background: pink;
}
.boxTwo {
margin: 30px;
height: 50px;
width: 70px;
border: solid black 2px;
background: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="app"></div>
Upvotes: 1
Reputation: 638
Let me explain what I have done.
event.target.classList
(which returns the list of the class current target have) and check that anyone from the classList exists to the state wrapperRefs.If it does not exists then it is click outside the component. I hope this helps you.
If you have any doubt comment below. I would like to help you as much as I can.
class App extends React.Component {
constructor() {
super();
this.state = {onClick: false, wrapperRefs: ['boxOne', 'boxTwo']};
this.handleClick = this.handleClick.bind(this);
}
componentDidMount() {
document.addEventListener('mousedown', this.handleClick);
}
componentWillUnmount() {
document.removeEventListener('mousedown', this.handleClick);
}
handleClick(event) {
const classes = event.target.classList;
const exists = this.state.wrapperRefs.some(ref => classes.contains(ref));
if(!exists) {
this.setState({onClick: !this.state.onClick});
}
}
render() {
return (
<section>
<div className="boxOne container" />
<div className="boxTwo" />
<div>{this.state.onClick ? "On" : "Off"}</div>
</section>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
.boxOne {
height: 100px;
width: 100px;
background: pink;
}
.boxTwo {
margin: 30px;
height: 50px;
width: 70px;
border: solid black 2px;
background: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="app"></div>
Upvotes: 0