Isomorphic flux on the server after all requests

I had trouble finding the best way to serve my processed components only after the http requests were resolved.

For instance:

component A - component B - component C (C launches an action that calls the API call and returns data for rendering, at the same time it just loads the "load").

When checking my source code, I see only the “download” and would like, for SEO purposes, to wait for the completion and visualization of the component C call.

In theory, this sounds simple, because the server itself must call this action and wait for the action to complete, then call react.renderToString(), for example:

server.get('/', function (req, res, next) {
    showMessages({}, function showMessagesCallback() { //add a callback
        var html = React.renderToString(ChatComponent());
        res.send(html);
    });
});

But what if several components make action calls, and I need to wait until several actions are resolved, and then call renderToString

. :

/**
 * This leverages Express to create and run the http server.
 * A Fluxible context is created and executes the navigateAction
 * based on the URL. Once completed, the store state is dehydrated
 * and the application is rendered via React.
 */

import express from 'express';
import path from 'path';
import serialize from 'serialize-javascript';
import {navigateAction} from 'fluxible-router';
import debugLib from 'debug';
import React from 'react';
import app from './app';
import HtmlComponent from 'components/Html';
const htmlComponent = React.createFactory(HtmlComponent);

const debug = debugLib('quran-com');

const server = express();
server.set('state namespace', 'App');
server.use('/public', express.static(path.join(__dirname, '/build')));
server.use('/images', express.static(path.join(__dirname, '/client/images')));
server.use('/fonts', express.static(path.join(__dirname, '/client/styles/fonts')));

server.use((req, res, next) => {
    let context = app.createContext();

    debug('Executing navigate action');
    context.getActionContext().executeAction(navigateAction, {
        url: req.url
    }, (err) => {
        if (err) {
            if (err.status && err.status === 404) {
                next();
            } else {
                next(err);
            }
            return;
        }

        debug('Exposing context state');
        const exposed = 'window.App=' + serialize(app.dehydrate(context)) + ';';

        debug('Rendering Application component into html');
        const html = React.renderToStaticMarkup(htmlComponent({
            context: context.getComponentContext(),
            state: exposed,
            markup: React.renderToString(context.createElement())
        }));

        debug('Sending markup');
        res.type('html');
        res.write('<!DOCTYPE html>' + html);
        res.end();
    });
});

const port = process.env.PORT || 8000;
server.listen(port);
console.log('Listening on port ' + port);

export default server;

?

+4
1

. , , - .

, , . , , , . :.

module.exports = {

    navigateAction: function (context, state, done) {
        var completeNavigation = function () {
            context.dispatch('NAVIGATE_DONE');
            done()
        }

        var route = _.last(state.routes);

        debug('navigate to: ' + route.name);

        switch (route.name) {
            case 'products':
                context.executeAction(productActions.loadProducts, null, completeNavigation);
                break;
            default:
                completeNavigation();
                break;
        }

    }

};

react-router.

0

All Articles