
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
react-onblur
Advanced tools
HOC for Blur (Unfocus) event handling of React component
npm i --save react-onblur
It is simple HOC function
import withOnBlur from "react-onblur";
// ...
export default withOnBlur(/* args */)(YourReactComponent);
which puts in your component two extra props
setBlurListener: function (callbackOrOptions: Function(event) or Object[, once: Boolean])
unsetBlurListener: function ()
setBlurListener should be called when you want to add events to document.callbackOrOptions: Function or Object.
onBlur: Function(event), required. It will be called once your component is unfocused or a user clicks outside of your component.once: Boolean, optional. The same that second argument of this function.checkInOutside: Function(domNode, isOutside): Boolean, optional. This function will be called always, when each of selected events are fired (e.g. when a user clicks on element on page or press key). It takes dom element target of an event and a Boolean sign that this element is outside. It should return Boolean value as sign that this element is outside. If it returns true then onBlur will be called. More information in next part of this doc.once: Boolean. If true then unsetBlurListener will be called after callback once your component is unfocused or a user clicks outside of your component.getRootNode: Function(this). Should return parent node, all targets out of this node will handle 'onBlur'.unsetBlurListener should be called when your want to remove events from document.(!!!) unsetBlurListener will be called in componentWillUnmount always.
TODO
You should create new component:
import React, { PureComponent } from "react";
import withOnBlur from "react-onblur";
class DemoComponent extends PureComponent {
state = {
isOpened: false
};
componentDidUpdate(prevProps, prevState) {
const { isOpened } = this.state;
// `setBlurListener` and `unsetBlurListener` props were added by withOnBlur
const { setBlurListener, unsetBlurListener } = this.props;
if (isOpened !== prevState.isOpened) {
// if our list was opened, then we will add listeners,
if (isOpened) setBlurListener(this.onBlur);
// else we will remove listeners
else unsetBlurListener();
// or
// if (isOpened) setBlurListener(this.onBlur, true);
// or
// if (isOpened) setBlurListener({ onBlur: this.onBlur, once: true })
}
}
onClickOpen = () => this.setState({ isOpened: true });
onBlur = () => this.setState({ isOpened: false });
render() {
return (
<div>
<button onClick={this.onClickOpen}>
Open list
</button>
{this.state.isOpened && (
<ul>
// ... list items
</ul>
)}
</div>
);
}
}
export default withOnBlur({ debug: true })(DemoComponent);
Next, you can use this component in your App:
function App() {
return (
<div className="App">
<div>
<button>Outside button</button>
</div>
<DemoComponent />
<div>
<button>Second outside button</button>
</div>
</div>
);
}
| args | type | default | description |
|---|---|---|---|
listenClick | bool | true | when true will add mousedown event for document |
listenTab | bool | true | when true will add keyup and keydown listeners for document to check Tab key press |
listenEsc | bool | true | when true will add keydown event for document to check Esc key is pressed |
debug | bool | false | when true will write debug messages to console |
autoUnset | bool | false | if true then unsetBlurListener will be called after callback action call once your component is unfocused or user will click outside of your component |
import withOnBlur from "react-onblur";
// ...
export default withOnBlur({
listenClick: true,
listenTab: false,
debug: true,
autoUnset: true
})(YourReactComponent);
checkInOutside? And why you should use it?If you use ReactDOM.createPortal then you can put element to another parent and it will not be child by DOM tree. But you can use checkInOutside to say about it to react-onblur.
import React, { PureComponent } from "react";
import ReactDOM from 'react-dom';
import withOnBlur, { isDomElementChild } from "react-onblur";
class DemoPortalComponent extends PureComponent {
state = {
isOpened: false
};
domMenu = React.createRef();
componentDidUpdate(prevProps, prevState) {
const { isOpened } = this.state;
const { setBlurListener, unsetBlurListener } = this.props;
if (isOpened && isOpened !== prevState.isOpened) {
setBlurListener({
checkInOutside: this.checkInOutside,
onBlur: this.onBlur,
once: true
})
}
}
onClickOpen = () => this.setState({ isOpened: true });
onBlur = () => this.setState({ isOpened: false });
checkInOutside = (element, isOutside) => (
// if it is in outside then we should check that it is not in our list,
// which was moved to body by createPortal
// For it we can use `isDomElementChild(parent, node)` from `react-onblur`
// and if element is child of list then it returns false.
isOutside && !isDomElementChild(this.domMenu.current, element)
);
render() {
return (
<div>
<button onClick={this.onClickOpen}>
Open list
</button>
{this.state.isOpened && (
ReactDom.createPortal(
<ul ref={this.domMenu}>
// ... list items
</ul>,
document.querySelector('body')
)
)}
</div>
);
}
}
export default withOnBlur()(DemoPortalComponent);
Check that node is child of parent.
isDomElementChild: Function(parent: DomNode, node: DomNode): Boolean
import withOnBlur, { isDomElementChild } from "react-onblur";
isDomElementChild(document.querySelector('body'), document.querySelector('div'));
// true for <body><div>1</div></body>
https://monosnap.com/file/gUeMnlLBE29xKzytdXsxBcZOtkpEtm
https://codesandbox.io/embed/n9r236n2xl
FAQs
HOC for Blur (Unfocus) event handling of React component
We found that react-onblur demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.