I'm attempting to use the React Idle Timer to go to a lock screen after 15 minutes.
The problem I am having is redirecting the page. I am using electron with react and the react BrowserRouter. Because of this I can't use window.location.assign('/clock'); (or similar window.location) method to redirect the page. Typically in my ponents I use:
this.props.history.push("/clock");
This works within the ponents that are within the Switch of the BrowserRouter. However, I need the React Idle Timer to be at the top level and when I use props.history.push inside the onIdle function I get the message:
Uncaught TypeError: Cannot read property 'push' of undefined
class AppRouter extends Component {
constructor(props) {
super(props);
this.idleTimer = null;
this.onAction = this._onAction.bind(this);
this.onActive = this._onActive.bind(this);
this.onIdle = this._onIdle.bind(this);
}
_onAction(e) {
console.log("user did something", e);
}
_onActive(e) {
console.log("user is active", e);
console.log("time remaining", this.idleTimer.getRemainingTime());
}
_onIdle(e) {
console.log("user is idle", e);
console.log("last active", this.idleTimer.getLastActiveTime());
//need to push to /clock after 15 minutes
//window.location.assign('/clock'); -- WORKS in browser, but not with Electron
// this.props.history.push("/clock"); -- gives Uncaught TypeError: Cannot read property 'push' of undefined
//can't place <IdleTimer inside BrowserRouter because it only allows 1 thing within.
}
render() {
return (
<div>
<IdleTimer
ref={ref => {
this.idleTimer = ref;
}}
element={document}
onActive={this.onActive}
onIdle={this.onIdle}
onAction={this.onAction}
debounce={250}
timeout={1000 * 60 * 0.1}
/>
<BrowserRouter>
<div>
<Switch>
<Route path="/institution" ponent={Institution} />
<Route path="/location" ponent={Location} />
<Route path="/timezone" ponent={TimeZone} />
<Route path="/clock" ponent={Clock} />
<Route path="/" ponent={PreflightCheck} />
</Switch>
</div>
</BrowserRouter>
</div>
);
}
}
ReactDOM.render(<AppRouter />, document.getElementById("root"));
I'm attempting to use the React Idle Timer to go to a lock screen after 15 minutes.
The problem I am having is redirecting the page. I am using electron with react and the react BrowserRouter. Because of this I can't use window.location.assign('/clock'); (or similar window.location) method to redirect the page. Typically in my ponents I use:
this.props.history.push("/clock");
This works within the ponents that are within the Switch of the BrowserRouter. However, I need the React Idle Timer to be at the top level and when I use props.history.push inside the onIdle function I get the message:
Uncaught TypeError: Cannot read property 'push' of undefined
class AppRouter extends Component {
constructor(props) {
super(props);
this.idleTimer = null;
this.onAction = this._onAction.bind(this);
this.onActive = this._onActive.bind(this);
this.onIdle = this._onIdle.bind(this);
}
_onAction(e) {
console.log("user did something", e);
}
_onActive(e) {
console.log("user is active", e);
console.log("time remaining", this.idleTimer.getRemainingTime());
}
_onIdle(e) {
console.log("user is idle", e);
console.log("last active", this.idleTimer.getLastActiveTime());
//need to push to /clock after 15 minutes
//window.location.assign('/clock'); -- WORKS in browser, but not with Electron
// this.props.history.push("/clock"); -- gives Uncaught TypeError: Cannot read property 'push' of undefined
//can't place <IdleTimer inside BrowserRouter because it only allows 1 thing within.
}
render() {
return (
<div>
<IdleTimer
ref={ref => {
this.idleTimer = ref;
}}
element={document}
onActive={this.onActive}
onIdle={this.onIdle}
onAction={this.onAction}
debounce={250}
timeout={1000 * 60 * 0.1}
/>
<BrowserRouter>
<div>
<Switch>
<Route path="/institution" ponent={Institution} />
<Route path="/location" ponent={Location} />
<Route path="/timezone" ponent={TimeZone} />
<Route path="/clock" ponent={Clock} />
<Route path="/" ponent={PreflightCheck} />
</Switch>
</div>
</BrowserRouter>
</div>
);
}
}
ReactDOM.render(<AppRouter />, document.getElementById("root"));
What is the correct way to redirect to a ponent at the top level outside of the BrowserRouter tags?
I have also tried this:
import { createHashHistory } from 'history'
export const history = createHashHistory()
and then calling history.push('/clock');
That only seems to append /clock to the current page that I am on and I get this message:
Hash history cannot PUSH the same path; a new entry will not be added to the history stack
Share
Improve this question
edited May 31, 2019 at 19:38
johnsonjp34
asked May 31, 2019 at 18:35
johnsonjp34johnsonjp34
3,2995 gold badges26 silver badges51 bronze badges
4
- Since routes are just ponents now, maybe it makes sense to move the idle-timeout behavior into a new ponent that wraps the routes? Then you could use history.push as you usually do. – Alex Broadwin Commented May 31, 2019 at 18:41
- You can use withRouter: reacttraining./react-router/web/api/withRouter – dahliacreative Commented May 31, 2019 at 19:04
- Does IdleTimer not allow you to pass children? You could replace the div inside the BrowserRouter with the IdleTimer then have the switch sit inside that if so. – dahliacreative Commented May 31, 2019 at 19:05
- The history.push continues to work fine in the other ponents. I need it to work inside the onIdle action method that is above the render area. – johnsonjp34 Commented May 31, 2019 at 19:36
2 Answers
Reset to default 2Create history (you can use npm install history):
import { createBrowserHistory } from "history";
const history = createBrowserHistory();
Then place the idle timer within Router. BrowserRouter does not seem to work with history like Router does in this situation.
<Router history={history}>
<div>
<IdleTimer
ref={ref => {
this.idleTimer = ref;
}}
element={document}
onActive={this.onActive}
onIdle={() => this.checkplayerstatus(history)}
onAction={this.onAction}
debounce={250}
timeout={1000 * 60 * 15}
/>
<Switch>
<Route path="/institution" ponent={Institution} />
<Route path="/location" ponent={Location} />
<Route path="/timezone" ponent={TimeZone} />
<Route path="/clock" ponent={Clock} />
<Route path="/" ponent={PreflightCheck} />
</Switch>
</div>
</>
And then in the onIdle function you can do this: "whatevervariableyoupassashistoryfromonidle".push("/clock").
If you are using tsx means ,
_onIdle=(e)=> {
window.location.href = "/your_location";
}
or if you are using js means,
_onIdle=(e)=> {
window.location = "/your_location";
}
<IdleTimer
ref={ref => {
this.idleTimer = ref;
}}
element={document}
onActive={this.onActive}
onIdle={this.onIdle}
onAction={this.onAction}
debounce={250}
timeout={1000 * 60 * 15} // 15 minutes
/>