web-dev-qa-db-fra.com

React + Flux et rendu côté serveur? (Isomorphic React + Flux)

Quelle est la pratique générale de définir l'état initial de l'application avec des applications isomorphes? Sans Flux, j'utiliserais simplement quelque chose comme:

var props = { }; // initial state
var html = React.renderToString(MyComponent(props);

Rendez ensuite ce balisage via guidons express et affichez-le via {{{reactMarkup}}.

Du côté client pour définir l'état initial, je ferais quelque chose comme ceci:

if (typeof window !== 'undefined') {
    var props = JSON.parse(document.getElementById('props').innerHTML);
    React.render(MyComponent(props), document.getElementById('reactMarkup'));
}

Donc oui, essentiellement, vous définissez l'état deux fois, sur le serveur et le client, cependant React comparera les différences et dans la plupart des cas, cela n'affectera pas les performances en effectuant un nouveau rendu).


Comment ce principe fonctionnerait-il lorsque vous avez des actions et des magasins dans l'architecture Flux? Dans mon composant, je pourrais faire:

getInitialState: function() {
  return AppStore.getAppState();
}

Mais maintenant, comment puis-je définir l'état initial dans l'AppStore du serveur? Si j'utilise React.renderToString Sans propriétés transmises, il appellera AppStore.getAppState() qui n'aura rien dedans car je ne comprends toujours pas comment définir l'état dans ma boutique sur le serveur ?

Mise à jour du 5 février 2015

Je suis toujours à la recherche d'une solution propre qui n'implique pas l'utilisation d'implémentations Flux tierces comme Fluxible, Fluxxor, Reflux.

Mise à jour du 19 août 2016

Utilisez Redux .

42
Sahat Yalkabov

Si vous êtes prêt à travailler avec alt.js vous pouvez y parvenir avec alt.bootstrap et alt.flush ( documents )

J'utilise le nœud js avec le rendu côté serveur React et alt.js comme implémentation de flux.

Voici à quoi ça ressemble:

var data = {}; // Get the data whatever you want and return it bootstrap ready.

// Reminder - renderToString is synchronised
var app = React.renderToString(
     AppFactory(data)
);

// In this point the react rendering was finished so we can flush the data and reset the stores

alt.flush();

Dans mon app.jsx

/**
 *
 */
componentWillMount: function () {

    // This beauty here is that componentWillMount is run on the server and the client so this is all we need to do. No need for other third-party isomorphic frameworks

    alt.bootstrap(
        JSON.stringify(this.props, null, 3)
    );

}
1
Rotem

Jetez un œil à dispatchr et aux bibliothèques associées de yahoo.

La plupart des implémentations de flux ne fonctionnent pas dans node.js car elles utilisent des singleton stockés, des répartiteurs et des actions, et n'ont aucune notion de "nous avons terminé" qui est nécessaire pour savoir quand effectuer un rendu en html et répondre à la demande.

Les bibliothèques de Yahoo comme fetchr et routr contournent cette limitation de nœud en utilisant une forme très pure d'injection de dépendance (pas de fonctions d'analyse pour les noms d'arguments ou quelque chose comme ça).

Au lieu de cela, vous définissez des fonctions api comme celle-ci dans services/todo.js :

create: function (req, resource, params, body, config, callback) {

Et des actions comme celle-ci dans actions/createTodo.js :

module.exports = function (context, payload, done) {
    var todoStore = context.getStore(TodoStore);
...
context.dispatch('CREATE_TODO_START', newTodo);
...
context.service.create('todo', newTodo, {}, function (err, todo) {

La dernière ligne appelle indirectement la fonction create dans services/todo.js. Dans ce cas, indirectement, cela peut signifier:

  • sur le serveur:
    • fetchr remplit les arguments supplémentaires lorsque vous êtes sur le serveur
    • il appelle ensuite votre rappel
  • côté client:
    • le client fetchr fait une requête http
    • fetchr sur le serveur l'intercepte
    • il appelle la fonction de service avec les arguments corrects
    • il renvoie la réponse au client fetchr
    • le fetchr côté client gère l'appel de votre rappel

Ce n'est que la pointe de l'iceberg. Il s'agit d'un groupe de modules très sophistiqués qui travaillent ensemble pour résoudre un problème difficile et fournir une API utilisable. L'isomorphisme est intrinsèquement compliqué dans les cas d'utilisation du monde réel. C'est pourquoi de nombreuses implémentations de flux ne prennent pas en charge le rendu côté serveur.

Vous pouvez également envisager de ne pas utiliser de flux. Cela n'a pas de sens pour toutes les applications et gêne souvent. Le plus souvent, vous n'en avez besoin que pour quelques parties de l'application, le cas échéant. Il n'y a pas de balles d'argent dans la programmation!

14
Brigand

FakeRainBrigand a raison de dire que le plus gros problème avec Flux côté serveur concerne les singletons. Flummox résout ce problème en n'utilisant pas de singletons et en vous permettant d'encapsuler l'ensemble de votre configuration Flux dans une seule classe réutilisable. Ensuite, vous créez simplement une nouvelle instance à chaque demande. Combiné avec une solution de routage comme React Router, vous pouvez créer des applications entièrement isomorphes.

Même si vous ne voulez pas utiliser Flummox, la source est facile à rechercher et vous pouvez l'utiliser comme un guide pour préparer vous-même quelque chose:

https://github.com/acdlite/flummox

3
Andrew Clark

Le problème est que lorsque vous recherchez "Rendu du serveur Flux" , vous vous heurtez immédiatement à cette question et il n'y a aucune mention de Redux , faite par communauté React.js rackt . Vous pouvez trouver bien décrit sur Redux documentation pourquoi le rendu du serveur est important, pourquoi nous devons envoyer l'état initial dans le HTML au client (c'est là que Flux devient insuffisant) et comment faire alors.

0
Tommz