javascript - helmet - react meta tags
Cómo manejar la solicitud de publicación en el enrutador Isomorphic React+React (1)
Obteniendo datos "POST" en el cliente
En el lado del cliente, obtiene datos POST al extraer valores de las entradas de su formulario de una manera que corresponde a lo que habría recibido en el servidor si el formulario hubiera sido enviado normalmente.
Uso de datos POST
Así que ahora tiene sus datos POST, pero sigue teniendo el problema de que no hay forma de incluir los datos POST en sus enlaces de transición en React Router 0.13.xy versiones anteriores. Creé una solicitud de extracción para esta función que ahora se ha cerrado porque se incluyó como parte de la reescritura para la próxima versión v1.0.
La esencia de esto es que las ubicaciones ahora tienen un objeto de estado para eliminar cualquier información adicional que necesite sobre la solicitud / transición actual (las dos son análogas) que se manejan:
- En el servidor, usted está tratando con una solicitud a la vez, por lo que crea una ubicación estática con datos de
req.body
- En el cliente, se pasa el objeto de estado (que contiene datos de formulario extraídos) a
transitionTo()
.
Ahora su enlace de transición es capaz de recibir los mismos datos de formulario en ambos entornos. Si las cosas van bien, ¡genial! Si las cosas no van bien, necesita una forma de pasar los errores y volver a renderizar el formulario. ¡Nuevo objeto estatal al rescate de nuevo! Use transition.redirect()
y pase tanto los datos de entrada como los errores y ahora tiene todo lo que necesita para renderizar en ambos lados.
No voy a entrar en detalles más específicos ahora porque v1.0 todavía está en versión beta y v0.13.x no tiene la API necesaria para hacer esto de todos modos, pero tengo un repositorio que utiliza la solicitud de extracción anterior para implementar este flujo de trabajo con 0.13.x que podría mirar mientras tanto:
- isomorphic-lab : el README ofrece una visión general de cómo encajan las cosas.
Aquí hay algunos diagramas de flujo del proceso, también:
Servidor POST con errores y redisplay.
Cliente POST con errores y redisplay.
También he creado algunos módulos reutilizables relacionados con este escenario:
- get-form-data obtiene datos de las entradas de un formulario en el formato en el que se hubieran enviado.
- react-auto-form proporciona
<AutoForm>
, que puede usar en lugar de<form>
para recibir todos los datos de las entradas de un formulario como un argumento para su controladoronSubmit
- react-router-form , que es
<form>
lo que React Router<Link>
es<a>
: maneja una transición a laaction
dada, elmethod
paso y el estado delbody
(datos del formulario); esto se actualizará para v1 .0 pronto.
Quiero crear la aplicación Isomorphic react
+ react-router
y después de unos días en Google, ahora puedo lograr la aplicación isomórfica que solo maneja la solicitud GET.
Esto es lo que he hecho hasta ahora:
- Servidor de uso
react-router
para manejar todas las solicitudes -
react-router
llamará afetchData
funcionesfetchData
que residen en cada Vista de Reacción que coincida con la ruta. - Establezca los datos recuperados anteriormente en las propiedades de la Vista de Reacción y conviértalos en una
string
- Inyecte la
string
y los datos obtenidos antes comowindow.__STATE__
variable globalwindow.__STATE__
en HTML y entregue el HTML al cliente - Hemos renderizado exitosamente la aplicación React desde el servidor.
- Cuando el cliente termine de cargar nuestra aplicación React javascript, intentará renderizar. Pero pasamos el estado desde la
window.__STATE__
como accesorios de nuestra aplicación React, y React no volverá a reproducirse porque el estado es el mismo
El problema es que no funcionará con la solicitud POST / PUT / DELETE / WHATEVER. Cuando se maneja la solicitud GET, react-router
tiene información sobre params
y query
. Por ejemplo, si tenemos una ruta: /user/:uid
y el cliente solicita esta url: /user/1?foo=bar
, entonces los params
serían: {uid: 1}
y la query
sería {foo: ''bar''}
react-router
luego puede pasarlo a la función fetchData
para que conozca el usuario con uid
de 1 y haga lo que sea con la consulta foo
.
Mientras se encuentra en la solicitud POST, react-router
no conoce los parámetros POST. En el servidor, por supuesto, podríamos pasar los parámetros POST a la función fetchData
, pero ¿qué pasa con el cliente? No sabe cuáles son los parámetros POST.
¿Hay alguna forma en que el servidor pueda decirle al Cliente acerca de los parámetros POST? A continuación se muestra un ejemplo de mi vista de inicio de sesión. Deseo que cuando el usuario envíe el formulario, el servidor muestre un mensaje de error en caso de error, o lo redirija al panel de control en caso de éxito
fetchData.js
import whenKeys from ''when/keys'';
export default (authToken, routerState) => {
var promises = routerState.routes.filter((match) => {
return match.handler.fetchData;
}).reduce((promises, match) => {
promises[match.name] = match.handler.fetchData(authToken, routerState.params, routerState.query);
return promises;
}, {});
return whenKeys.all(promises);
}
server.js
...
app.use((req, res) => {
const router = Router.create({
routes,
location: req.originalUrl,
onError: next,
onAbort: (abortReason) => {
next(abortReason);
}
});
router.run((Handler, state) => {
fetchData(authToken, state).then((data) => {
// render matched react View and generate the HTML
// ...
})
});
});
...
login.jsx
import React from ''react'';
import DocumentTitle from ''react-document-title'';
import api from ''./api'';
export default class Login extends React.Component {
constructor(props) {
super(props);
// how to fill this state with POST parameters on error?
// how to redirect on success?
// and remember that this file will be called both from server and client
this.state = {
error: '''',
username: '''',
password: ''''
};
}
// I saw some people use this function, but it''ll only work if
// the form''s method is GET
static willTransitionTo(transition, params, query) {
// if only we could read POST parameters here
// we could do something like this
transition.wait(
api.post(''/doLogin'', postParams).then((data) => {
transition.redirect(`/dashboard`);
});
);
}
render() {
return (
<DocumentTitle title="Login">
<div className="alert alert-danger">{this.state.error}</div>
<form method="post">
<input type="text" name="username" value={this.state.username} onChange={this._onFieldChange(''username'')} placeholder="Username" /><br />
<input type="password" name="password" value={this.state.password} onChange={this._onFieldChange(''password'')} placeholder="Password" /><br />
<button type="submit">Login</button>
</form>
</DocumentTitle>
);
}
_onFieldChange(name) {
var self = this;
return (e) => {
e.preventDefault();
var nextState = {};
nextState[name] = e.target.value;
self.setState(nextState);
}
}
}