最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React Idle Timer with BrowserRouter - Stack Overflow

programmeradmin3浏览0评论

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
Add a ment  | 

2 Answers 2

Reset to default 2

Create 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
        />
发布评论

评论列表(0)

  1. 暂无评论