React-router: routerWillLeave triggers a second confirmation box if the user clicks "Cancel"

Created on 12 Nov 2015  路  10Comments  路  Source: ReactTraining/react-router

When routerWillLeave returns text to trigger a confirmation, and the user clicks "Cancel" to abort the transition, the confirmation box appears again. This appears to be a result of routerWillLeave being called again. nextLocation appears to be the same both times routerWillLeave is called.

Expected: one confirmation box appears to the user. The confirmation box goes away if the user clicks "Cancel".

Test this by adding a routerWillLeave method that returns text.

bug

Most helpful comment

I think I know what's going on. We're trying to make tabs work (with warning when form's dirty) and we're using <a href="/#/some/route/here">go there!</a> for the links. When switching to <Link to="/some/route/here">go there!</Link> it is not triggering the double confirm.

EDIT I went through the docs and found a code sample with a comment saying one should use <Link>. In hindsight it's pretty obvious, but perhaps putting in a notice in the docs somewhere: "Do not use regular links expecting react-router to know how to work its magic". :)

All 10 comments

I can't reproduce this on the transitions example in RR. Can you reproduce it there?

I can't. It may be related to nested components using RouteContext mixin. I'll try to build a failing example.

Okay - also make sure that you haven't registered the same leave hook twice.

Can no longer reproduce. May have been an issue with an outdated version of Chrome. Closing.

We are seeing this exact issue here too, and I agree, it's like routerWillLeave is called twice (possibly during unbinding?). I've tried to go through the call-chain with the debugger but there's a lot going on there! :/

UPDATE Chrome behaves differently from FF. In Chrome this hack "works":

  routerWillLeave: function() {
    if (this._asked) {
      this._asked = false;
      return false;
    }
    if (this._isDirty) {
      this._asked = true;
      return "Your work is not saved! Are you sure you want to leave?";
    }
  },
  _isDirty: false,
  _asked: false, 

In FF it does not. FF also shows double confirmation prompts when pressing "Ok" so the issue is actually worse.

Chrome: v48.0.2564.23 beta (64-bit)
FF: 44.0a2 (2015-12-08)

You're somehow attaching multiple route leave listeners - if you disagree, give us a repro against the bundled navigation confirmation example.

@talon yeah, we must be doing something wrong. Thanks for the feedback. One question for you: can you point me to the code in react-router where the event listener is setup? I was thinking I'd drop a debugger there and try to figure out what's calling things multiple times.

I think I know what's going on. We're trying to make tabs work (with warning when form's dirty) and we're using <a href="/#/some/route/here">go there!</a> for the links. When switching to <Link to="/some/route/here">go there!</Link> it is not triggering the double confirm.

EDIT I went through the docs and found a code sample with a comment saying one should use <Link>. In hindsight it's pretty obvious, but perhaps putting in a notice in the docs somewhere: "Do not use regular links expecting react-router to know how to work its magic". :)

I wonder if we can do something when links are clicked to store that the hashchange triggered is actually from our own API and not just the browser's hash change on a normal anchor ...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

maier-stefan picture maier-stefan  路  3Comments

andrewpillar picture andrewpillar  路  3Comments

tomatau picture tomatau  路  3Comments

jzimmek picture jzimmek  路  3Comments

imWildCat picture imWildCat  路  3Comments