javascript - Cómo representar componentes inicializados de forma asíncrona en el servidor
reactjs (3)
Soy relativamente nuevo en ReactJS y he sido seducido por la facilidad de implementar la representación del lado del servidor para reducir el "tiempo para el primer tweet". Estoy ejecutando una pila Node-Express-React que pre-procesa el marcado en el servidor usando renderComponentToString de React.
Funciona bien cuando los componentes pueden procesarse de forma sincrónica, sin embargo, estoy teniendo problemas cuando se trata de implementar componentes poblados por ajax (sin embargo, esto se aplica a cualquier operación asíncrona durante la inicialización del componente, por ejemplo, websocket).
Tome el ejemplo del sitio web de React: http://facebook.github.io/react/tips/initial-ajax.html
componentDidMount: function() {
$.get(this.props.source, function(result) {
var lastGist = result[0];
this.setState({
username: lastGist.user.login,
lastGistUrl: lastGist.html_url
});
}.bind(this));
No funcionará en el servidor, ya que componentDidMount nunca se activa cuando se utiliza renderComponentToString. Este caso simple se puede solucionar utilizando el mismo envoltorio de solicitud HTTP en el cliente y en el servidor (en lugar de usar $ .get de jQuery), y precargando los datos antes de crear una instancia del componente y pasarlo como prop.
Sin embargo, en una aplicación compleja y real, las dependencias asíncronas pueden complicarse mucho y la captura previa no se ajusta realmente al enfoque descendente de la construcción de estructuras React. ¿Cómo puedo implementar un patrón de inicialización asíncrono en React que pueda representarse en el servidor sin montar realmente nada (es decir, sin emulación de DOM a la PhantomJS, que es el objetivo de usar renderComponentToString)?
Creo que la forma más práctica de hacer esto es hacer un prop opcional para los datos precargados, como por ejemplo:
getInitialState: function() {
if (this.props.initialLastGist) {
var lastGist = this.props.initialLastGist;
return {
username: lastGist.user.login,
lastGistUrl: lastGist.html_url
};
} else {
return {};
}
},
componentDidMount: function() {
if (!this.props.initialLastGist) {
$.get(this.props.source, function(result) {
var lastGist = result[0];
this.setState({
username: lastGist.user.login,
lastGistUrl: lastGist.html_url
});
}.bind(this));
}
},
Con una configuración como esta, el componente se puede procesar inmediatamente si los datos precargados están presentes; De lo contrario, la solicitud AJAX se enviará durante el montaje.
Actualmente, la representación del servidor siempre es síncrona y componentDidMount
no se llama en el servidor porque generalmente implica la manipulación de DOM. Lo siento, no tengo una solución mejor aquí ahora mismo, pero en general desea minimizar la cantidad de solicitudes HTTP al servidor, por lo que vale la pena analizar su arquitectura para poder recopilar toda la información que necesita en el servidor.
Podría echar un vistazo al proyecto react-quickstart , que utiliza react-async
y se envía con un ejemplo de representación del servidor. react-async
proporciona un método renderComponentToString
decorado que renderComponentToString
estado asíncrono y lo convierte en el marcado inicial. Sin embargo, deberá especificar el estado asíncrono por separado del estado "regular".
puede consultar react-nexus ( https://github.com/elierotenberg/react-nexus ) que le ayuda a declarar todas sus dependencias asíncronas con anticipación.
pero me doy cuenta de que reaccion-nexus es su propia respuesta a este problema, ¡así que probablemente ya lo haya encontrado!