solid-router
solid-router copied to clipboard
Support for blocking navigation (via integration)
Adds minimal core support for blocking navigation. Use case is providing some control over navigating away from a route that has unsaved changes.
Leaving a route can occur in many ways - and blocking them all is challenging:
- User clicks a normal anchor
- User clicks a router
<A>
component - Code calls navigate
- Code calls browser history APIs directly
- User refreshes the page
- User types in URL
- more?...
Some of these can be handled somewhat in user land, eg by listening to window.beforeunload
for (5 & 6), but others need some assistance from router.
In Solid's case, blocking seems relevant in two places:
a) The router internals (ie the navigateFromRoute
function) handles 2 & 3
b) The router integration (ie suppress notifying the location has changed) handles 1.
This PR is specific to (a) and enables (b). It enables the router integration to optionally provide a block
function that will bail out of navigateFromRoute
.
It is expected that block
function will originate from the app, probably as an option to the integration. It is also likely the block
function will itself be used to support some higher-level component such as a useBlocker
hook - but these may be best experimented with in userland via custom integrations. It is noteworthy the parameters to the block
function are the same as those used when calling navigate
. This is intentional as the app may wish to save those parameters and block immediate navigation - and then kick navigation off again in the near future - for example if the user confirms they are okay to leave the page without saving.
Note This PR does not update the built-in integrations to utilize the
block
function. I have tested with a custom integration here that implements (b) - but I think that is a separate concern.
To clarify why the block
function needs to be available to the router integration (in addition to the internals)...
...in the event of a navigation being blocked, the integration (path, hash, etc) needs to revert the browser url state appropriately eg window.history.go(-1)
, while also preventing notifying the router of both the original url change and the one caused by the "revert". That process may differ by integration?
If your curious, this commit (~~https://github.com/cselnz/solid-router/commit/772615038535562b619f7d63479f9df5f95fefe7~~) suggest how this new block ability might be used in the integrations. Note - I'm testing that in our apps using hash integration - so the path integration will need further testing.
~~EDIT: this one does the proper depth thing when reverting the url ( https://github.com/cselnz/solid-router/commit/920d6fb96ad9a76e1d9217e9c1c26251f16562ff)~~
Okay now, after several commits and a day of tuning, we've got a branch that implements the integrations using the hook PR ...soon to be in production in our apps. https://github.com/cselnz/solid-router/tree/publish
Scrapping this in favour the much more comprehensive PR https://github.com/solidjs/solid-router/pull/186