-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
Description
If react-router had a <Form> component (which would be to <form> as <Link> is to <a>), what could it do to make it simpler to implement form submission and - in particular - isomorphic form submission?
The obvious-seeming bit is that it could hook up onSubmit for you to call preventDefault() and slurp all the form data out via form.elements into an object which represents what would be submitted by a regular form submission.
If it's a GET form, it could then trigger a transition (to a named actionTo or to route, with the resolved URL set as the rendered <form>'s action?) with the data as query parameters.
The above functionality would completely negate the need for the onSubmit handler in in the mega demo form component, which seems like a good start that's worth having.
As background to the design questions I'm about to ask, the additional bits I'm grappling with in isomorphic-lab are:
- Isomorphic POST forms
- Using the same route handler for both GET (display form) and POST (validate form, call API, display any API errors or redirect on success) parts of submitting a form
- Performing validation prior to submission and only triggering a transition to do the POST part when valid, as a progressive enhancement when JavaScript is available.
- Avoiding reflecting POSTed data back to the user in the URL, where possible.
I am currently displaying a flash of POSTed data back to the user in the query string on submission by faking a POST transition to the same route:
this.transitionTo(
this.makeHref('addReply'),
{},
assign({_method: 'POST'}, form.data)
)For redisplay of a form with errors, I currently have an ugly hack which. To avoid displaying the POSTed data back to the user in the query string, I do this in willTransitionTo:
if (res.clientError) {
if (env.CLIENT) {
// Update the form with validation errors received from the API
events.emit(AddReply.ERRORS_EVENT, ErrorObject.fromJSON(res.body))
transition.abort()
}
else {
// Re-render with user input + validation errors from the API
transition.abort(new Render(`/forums/topic/${params.id}/add-reply`, {
initialData: query
, initialErrors: res.body
}))
}
}An EventEmitter is used on the client to pass errors from willTransitionTo to the currently mounted form component, while on the server my Express middleware takes the Render object, re-runs the routers and passes the additional object's properties as extra props to the <Handler>.
Design Questions
POST data
Regular POST data:
- is never displayed to the user in the query string
- isn't bookmarkable
- BUT can be sent again by refreshing the page if there was no redirect
The current arguments passed to willTransitionTo represent things which (if provided) can be seen in the URL. I feel like this should not be the case with POST data.
Is it feasible to add another argument for one-shot data which isn't represented in the URL to be passed to transition hooks?
What about the behaviour in 2i? If the ability to pass POST data to a transition is added, should 2i be written off as a loss? I assume any attempt to emulate (e.g. confirm() in a transition) is beset with all sorts of cross-platform/device concerns.
(more to follow later!)