-
-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Support additional state that is not in the URL #828
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
Conversation
@insin Thank you for this PR! I haven't had a chance to look very deep yet, but I did push a version of |
@insin This is really interesting work. It helps me realize a few areas where our API is lacking and/or docs are missing or aren't clear. Thank you :) I'm still trying to wrap my head around the core concept you're introducing here and use cases you're trying to support. Please correct me if I'm wrong, but it seems like if you were using the HTML5 history API directly your If so, I'd say it's definitely something we'd like to support. |
@mjackson My initial use case was "POST data doesn't belong in the URL" then it also became "data I have in an async Since I'm using routes and route handlers isomorphically, I added an additional parameter to The only way to get data directly out of a Now that you mention it, I can see how something similar could be used for, or as an equivalent to, the |
Thanks for the explanation. Since our current API wasn't built to hold state anywhere but the URL path, I think you're probably jumping through some hoops you shouldn't have to if we were to support this properly. :) Ignoring our current architecture, what I'm hearing from you is there is some state at the application level that you want to be able to tie to a particular invocation of a route that doesn't really belong in the URL. Examples of this extra state include:
Re: the It seems you're on the right track adding your One big question I have is how we might implement this across our other location objects. Still trying to wrap my head around this :) |
I think the important thing to decide here is whether the payload should be persisted for history navigation (back/forward), or only used for the next run callback. It seems to me that for POST data, you'd only want to use that once (otherwise you'd probably want to add an extra confirmation dialog for when you go back to that page using back button - like browsers do themselves). If it should be coupled to history navigation, the feature could make use of #828 by using the history key and managing the payloads within the router (could also be saved to sessionStorage), or it could also directly use the state object. The huge downside, however, is that it won't work reliably with |
Please note: this commit is still a work in progress! All history objects subclass History and support 2 main methods: - pushState(state, path) - replaceState(state, path) This API more closely matches the HTML5 history API, with the notable omission of the title argument which is currently ignored in all major browsers. It provides the user with the ability to store state specific to the current invocation of the current URL without storing that data in the URL itself. However, history objects that do not use the HTML5 history API (HashHistory and RefreshHistory) store their state ID in the query string. This should help with #767 and #828. This work was inspired by work done by @taurose in #843 and @insin in #828.
At first I was like "what?" but then if you think about things as "requests" and not "urls" it makes a lot of sense. This would also allow people to send along "context" information that they want access to in their transitions (like flux containers and such). Also if you think about a browser's back button saying "this will cause a repost", url transitions absolutely have non-url data attached to them. I'm 👍 on supporting a transition context/state arg. |
+1 |
Updating the PR's branch again to rename the new object it introduces from If there's an opportunity to make a breaking change to willTransitionTo(transition, context[, callback]) {
// context.params
// context.query
// context.data
} I'd almost be tempted to call it |
I like putting |
The need to pass empty params/query objects when you don't need them is ugly, an options object is ugly too in a different way but not having to remember order is a win. Another one for the "Reasons I wish JavaScript had Python-style kwargs" list. |
The data argument isn't reflected in the URL - it's intended for: 1. Passing one-time data to willTransitionTo hooks without having to send it through the URL (e.g. POST form data) 2. Passing one-time props via a redirect, to be used in a route handler (e.g. user input and validation errors from a service call which need to be redisplayed)
+1 And I think having a proper Request object (with params, query and body) aligned with what we have on node would be awesome and a huge win for isomorphic app development. I'm working on a fork of react-router which does exactly that (together with a Form element, which is like a Link which passes a req.body). Having it natively in react-router would be awesome. To reply some of the criticism: I don't think we should store the additional data somewhere, having the same behaviour as a simple POST request (where data is available just once when you issue the request) is probably the thing most people are used to. |
I have a Form component which does that, too: https://github.com/insin/react-router-form Just waiting to see how this will fit into the 1.0 API. |
Oh that's great, looking forward to it |
Its in! Need more docs around it, but here's a tiny bit. https://rackt.github.io/react-router/tags/v1.0.0-alpha1.html#-transitionto-pathname-query-state- |
Wunderbar! |
Starting a PR to discuss a feature addition which solved the problems I was having in #792 with form submission and redisplay without having to funnel everything through
query
.This adds a new
payload
parameter tolocation.push()
andlocation.replace()
, the other API methods which ultimately use them,willTransitionTo
hooks and as a new property of thestate
object passed to therouter.run()
callback.It also replaces internal use of strings for static locations with aStaticLocation
constructor in order to be able to pass a payload object when running on the server.I've used this in the payload branch of insin/isomorphic-lab with the History location on the client and the new Static location on the server, and in this modified version of the Mega Demo contacts form with the Hash location.
Examples:
run()
callbackNow that I have the basics I needed working, there's other stuff I just fudged my way around or didn't really look at properly, such as:
Oh yeah, and is this a feature you want, or is having a built-in way to bypass the URL a bit naughty for a router? 😄