-
-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(preact-iso): Use pushState/ replaceState for useLocation().route method #413
base: main
Are you sure you want to change the base?
(preact-iso): Use pushState/ replaceState for useLocation().route method #413
Conversation
🦋 Changeset detectedLatest commit: 3d0d9f4 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this was already supported?
route('/url', true)
(admittedly, push=true
might be a better default)
@@ -8,7 +8,7 @@ interface LocationHook { | |||
url: string; | |||
path: string; | |||
query: Record<string, string>; | |||
route: (url: string) => void; | |||
route: (url: string | { url: string, replace?: boolean }) => void; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if we can use (url, replace)
here? That would match preact-router
.
@developit wmr/packages/preact-iso/router.js Lines 44 to 51 in 58f1bff
Probably we would have to refactor router code to not use reducer in this case (which may be not a bad idea to handle history outside/ without reducer). |
I prefer |
I've created new PR in #424 to fix the bug with location change after using After it's resolved it will be easier to move forward with adding an option such as |
Nice - thanks for pulling that out, just merged it. |
packages/preact-iso/router.js
Outdated
url = location.pathname + location.search; | ||
// manual invocation: route({ path, replace }) | ||
} else if (typeof url === 'object') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's what I'd suggest, in order to preserve the duck typing (as mentioned in previous comment):
const UPDATE = (state, update) => {
/** @type {boolean|undefined} - History state update strategy */
let push, url;
if (!update || typeof update === 'string') {
url = update;
push = true;
}
else if (update.type === 'click') {
// user click
// @ts-ignore-next
const link = update.target.closest('a[href]');
if (!link || link.origin != location.origin) return state;
update.preventDefault();
url = link.pathname + link.search + link.hash;
push = true;
}
else if (update.type === 'popstate') {
// navigation
url = location.pathname + location.search + location.hash;
}
else {
// manual invocation: route(url) or route({ url, replace })
url = update.url || update;
push = !url.replace;
}
if (push === true) history.pushState(null, '', url);
else if (push === false) history.replaceState(null, '', url);
return url;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we allow passing a value that evaluates to false (undefined/ null) with route method?
If so, then should it be added to history?
if (!update || typeof update === 'string') {
// ^
When the update
is not either string or event I'd say it must be an object?
else {
// manual invocation: route(url) or route({ url, replace })
url = update.url || update;
// ^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated PR with code you suggested, adapting to eslint/ prettier rules
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@developit
What do you think about my comments above?
# Conflicts: # packages/preact-iso/router.js
I've updated PR to use code suggested in #413 (comment) However I'm not happy with the |
@piotr-cz I think we might be able to create a wrapper function in the provider that swaps the argument signature: - const [url, route] = useReducer(UPDATE, location.pathname + location.search);
+ const [url, doRoute] = useReducer(UPDATE, location.pathname + location.search);
+ const route = useCallback((url, replace) => doRoute({ url, replace }), []); It might even be possible to simplify the history event handling this way too. |
@developit |
Just one question: |
I'd go for patch yea |
At this moment when using
useLocation().route('/foobar')
window location doesn't change: neitherhistory.pushState
norhistory.replaceState
method is used.This pull request
pushState
.replaceState
Originally the useReducer hook dispatcher had a third
push
argument, but dispatchers consume only two arguments.wmr/packages/preact-iso/router.js
Line 4 in 58f1bff
I'm not sure if I should bump patch or minor version with changeset?