You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Not sure if this is a bug, but calling the retry method of history.block during render phase does not unblock navigation.
Version
React Router v6.0.0-beta.0
Test Case
The demo app has two pages Step1 and Step2. Step1 has a checkbox called 'Block navigation', which blocks navigation attempts when checked, and a 'Next' button that takes the user to Step2.
Blocking is done using useBlocker inside a wrapper hook called useCustomPrompt. The blocker callback passed to 'useBlocker' is called handleNavigation - it saves the retry method that is passed to it in a ref and displays a modal with a message to accompany the block. In this case, the message displayed is "Are you sure you want to leave?" with 'OK' and 'Cancel' buttons. The user clicks 'OK' to confirm navigation to Step2 (retry is called here) or 'Cancel' to cancel the navigation and remain on Step1.
Click the 'OK' button inside the "Are you sure you want to leave" prompt.
Expected Behavior
Navigation to Step2 is unblocked and reattempted when the user clicks 'OK'.
Actual Behavior
Navigation is reattempted but not unblocked, so the user remains on Step1 after clicking 'OK'.
Workaround
Calling retry after the render phase inside a useEffect works (link to demo).
Please correct me if I'm wrong but this seems to work due to the clean up of the effect in useBlocker, which calls unblock on clean up (see line 307 react-router/index.tsx and line 587 of history/index.ts). I tried setting up breakpoints to capture the effects:
When you click 'OK', a state variable proceed is toggled to true, which triggers a re-render. After the re-render, the clean up function of the useBlocker effect seems to be invoked and we go to line 234 (which clears the blockers array) and then to line 235 (which removes the beforeunload event since blockers.length === 0). Then my effect fires (line 42) and calls the retry method. But by this time blockers.length is already 0, so the call to unblock on line 562 is redundant and the transition is allowed to go through at the retry on line 563.
(As an aside, it's not clear what's causing the effect to clean up after the user clicks 'OK', since none of the dependencies [navigator, blocker, when] are changed by the user clicking 'OK'. Clicking 'Next' also triggers this clean up. I'd be grateful if someone could shed some light on why this is happening.)
The text was updated successfully, but these errors were encountered:
mkaizad
changed the title
useBlocker - Calling retry during render does not unblock navigation
[v6] - useBlocker - Calling retry during render phase does not unblock navigation
Jan 6, 2021
Outline
Not sure if this is a bug, but calling the
retry
method ofhistory.block
during render phase does not unblock navigation.Version
React Router v6.0.0-beta.0
Test Case
The demo app has two pages
Step1
andStep2
.Step1
has a checkbox called 'Block navigation', which blocks navigation attempts when checked, and a 'Next' button that takes the user toStep2
.Blocking is done using
useBlocker
inside a wrapper hook calleduseCustomPrompt
. The blocker callback passed to 'useBlocker' is calledhandleNavigation
- it saves theretry
method that is passed to it in aref
and displays a modal with a message to accompany the block. In this case, the message displayed is "Are you sure you want to leave?" with 'OK' and 'Cancel' buttons. The user clicks 'OK' to confirm navigation toStep2
(retry
is called here) or 'Cancel' to cancel the navigation and remain onStep1
.**Link to demo**
Steps to reproduce
Expected Behavior
Navigation to
Step2
is unblocked and reattempted when the user clicks 'OK'.Actual Behavior
Navigation is reattempted but not unblocked, so the user remains on
Step1
after clicking 'OK'.Workaround
Calling
retry
after the render phase inside auseEffect
works (link to demo).Please correct me if I'm wrong but this seems to work due to the clean up of the effect in
useBlocker
, which callsunblock
on clean up (see line 307 react-router/index.tsx and line 587 of history/index.ts). I tried setting up breakpoints to capture the effects:lbuu2.csb.app/example.js? [sm]
- lines 30 and 42lbuu2.csb.app/node_modules/react-router/index.js
- lines 554, 558, 562, 563lbuu2.csb.app/node_modules/history/index.js
- lines 234, 235When you click 'OK', a state variable
proceed
is toggled totrue
, which triggers a re-render. After the re-render, the clean up function of theuseBlocker
effect seems to be invoked and we go to line 234 (which clears theblockers
array) and then to line 235 (which removes thebeforeunload
event sinceblockers.length === 0
). Then my effect fires (line 42) and calls theretry
method. But by this timeblockers.length
is already 0, so the call tounblock
on line 562 is redundant and the transition is allowed to go through at theretry
on line 563.(As an aside, it's not clear what's causing the effect to clean up after the user clicks 'OK', since none of the dependencies
[navigator, blocker, when]
are changed by the user clicking 'OK'. Clicking 'Next' also triggers this clean up. I'd be grateful if someone could shed some light on why this is happening.)The text was updated successfully, but these errors were encountered: