I created the below HOC which I can use to wrap a React component to add 2 inactivity timers: the first to show the user a warning; the other to log them out. I got the idea from here and it seems to work pretty well. That is, I can add withTimer functionality to a component by wrapping it like this:
export default withTimer(DragDropContext(HTML5Backend)(App));
The problem is the warning alert box halts the event loop (as alert boxes apparently always do), so the logout function is never reached.
I believe a modal (e.g., from react-bootstrap) would solve this, as it presumably would not halt the event loop, thus the logout would occur as intended if the user is still idle after the warning alert.
How would I change the below HOC to use a modal for the warning instead of an alert box? Is this possible? That is, can a HOC that's used to wrap another component include a component itself (i.e., the modal) so as to keep it decoupled from the wrapped component itself?
import React from 'react';
import { Modal } from 'react-bootstrap';
const withTimer = (WrappedComponent) => {
class WithTimer extends React.Component {
constructor(props) {
super(props);
this.state = {
warningTime: 5000,
signoutTime: 10000
};
this.events = [
'load',
'mousemove',
'mousedown',
'click',
'scroll',
'keypress'
];
for (var i in this.events) {
window.addEventListener(this.events[i], this.resetTimeout);
}
this.setTimeout();
}
clearTimeoutFunc = () => {
if (this.warnTimeout) clearTimeout(this.warnTimeout);
if (this.logoutTimeout) clearTimeout(this.logoutTimeout);
};
setTimeout = () => {
this.warnTimeout = setTimeout(this.warn, this.state.warningTime);
this.logoutTimeout = setTimeout(this.logout, this.state.signoutTime);
};
resetTimeout = () => {
this.clearTimeoutFunc();
this.setTimeout();
};
warn = () => {
window.alert('You will be logged out soon. Click to stay logged in.');
};
logout = () => {
window.alert('You are being logged out!');
// log the user out here
};
render() {
console.log('HOC');
return <WrappedComponent {...this.props.children} />;
}
}
return WithTimer;
};
export default withTimer;