page.js
page.js copied to clipboard
easy to get caught in an infinite loop
Had a peak around the code as well as #30 , but couldn't figure it out. Here's an example:
boot.js:
page('/note/:slug', function() {
note.select();
});
// ...
page();
noteview.js:
NoteView.prototype.select = function(note) {
// ...
page('/note/' + note.slug); // INFINITE LOOP
};
I feel like before page redirects it should check if the pathname is the same. It looks like it does that in the unhandled function, but that function isn't getting called from page('/note/' + note.slug).
Maybe, I'm just looking for a way to not trigger the dispatch. Basically a way to "save my progress", where nothing gets triggered, just if I refresh, I'm back where I am.
It looks like history.pushState(null, null, '/note/' + note.slug) would do the trick. Is this piece of the API exposed in page?
the route itself does that already, that's like going to an express route that does a res.redirect() to itself
yah, this one is hard to explain and I'm probably approaching it wrong.
What I'd like to do is save the state, so if I refresh the page I'm back where I am.
In my case page is actually redirecting, which re-triggers the route and causes infinite loop.
but if that route is invoked you're already displaying that page, so there's no need to page() cyclicly. There's page.replace(path) if you're rewriting the path or doing something weird, that's the equivalent of history.replaceState
yah, the problem is that the route can get triggered two ways:
- direct the browser there (e.g.
/notes/blah), triggers the route, and loads the view - click on the note's link to
/notes/blah, triggers the route, and loads the view.
I've also bound the click function to, in this example select. What I can do is bind the click to another function that simply does page('/notes/blah'), but it'd be nice if page just knew that it shouldn't redirect when it's already there and I think it'd be a pretty easy fix by checking location.pathname.
I guess I don't get why there's one method for two things, howcome it cant be say note.render() (or whatever) and note.select() to programmatically do your page() call, but then at least it's non-cyclic logic
Umm, well they perform the same action (highlight the note, load a view), they are just triggered in two different ways (going to that url vs. clicking on the note). I did end up breaking it apart, but I definitely think there is a use case in being able to "silently" set a route.
actually silently setting the route would create doubles in the history, it would need to check if the route has already been triggered.
not a huge deal though, i found a work-around. i'll close this for now, and we can see if anyone else runs into this.
actually you know what, you're totally right hahaha, I just ran into this myself and it's definitely annoying
ahh, haha. awesome. yah, it's really hard to explain without seeing it yourself.
a year old still no fix :(
submit a PR :-)
:+1:
Just to clarify what the desired behavior is, we want to not dispatch when the pathname hasn't changed, is that right? I think this would have to be a semver major change, if we do it. I'm wondering if there is any use-case for dispatching on the current route.
Or actually I'm wondering is this change is desirable at all now that there are redirects: https://github.com/visionmedia/page.js#pagefrompath-topath
I still find this functionality desirable.
For example, an App may have navigation actions which can be triggered by either a url change or an app event. It makes sense for these actions to also update the path if called by an app event. However, if called by a url change this will cause an infinite loop.
Only dispatching when the path has changed solves this and provides an elegant solution for both app events and url changes to use the same actions.
If semver major version change is the concern, possibly a new option to allow this behavior. With a default set to the current functionality, as to not cause any issues.