Fluks isomorfik dirender di server setelah semua permintaan

Saya mengalami kesulitan dalam mencari cara terbaik agar server merender komponen reaksi saya hanya setelah permintaan http diselesaikan.

Misalnya:

komponen A ‹- komponen B ‹- komponen C (C memicu tindakan yang membuat panggilan ke API dan mengembalikan data untuk dirender, sementara itu hanya merender 'memuat').

Saat memeriksa kode sumber saya, saya hanya melihat 'memuat' dan ingin, untuk tujuan SEO, server menunggu hingga panggilan komponen C diselesaikan dan dirender.

Secara teori, hal ini terdengar mudah karena server harus memanggil tindakan itu sendiri dan menunggu hingga tindakan tersebut selesai, lalu memanggil react.renderToString(), seperti ini:

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

Namun bagaimana jika beberapa komponen melakukan panggilan tindakan dan saya harus menunggu beberapa tindakan diselesaikan lalu memanggil renderToString

Sebaliknya, permintaan diambil di sisi klien. File server saya:

/**
 * 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;

apa cara terbaik untuk melakukan ini?


person Mohamed El Mahallawy    schedule 17.05.2015    source sumber
comment
Saya tidak mengerti masalah apa yang ingin Anda selesaikan. Data apa yang harus dirender? Di mana itu diambil?   -  person WiredPrairie    schedule 17.05.2015
comment
Apa yang dirender di sisi server hanya ketika semua permintaan http telah kembali. berarti? Kumpulan permintaan HTTP apa yang Anda maksud? Dan apa maksudmu dengan dikembalikan? Apakah Anda punya contoh konkritnya?   -  person August Lilleaas    schedule 17.05.2015
comment
@WiredPrairie Saya memperbarui pertanyaan untuk menjelaskan dengan lebih baik   -  person Mohamed El Mahallawy    schedule 17.05.2015
comment
Anda harus menggunakan teknik untuk menunda render akhir hingga semua komponen telah mengambil datanya atau memusatkan permintaan data, dan sekali lagi, tunggu.   -  person WiredPrairie    schedule 18.05.2015
comment
@WiredPrairie, oke kedengarannya bagus - bagaimana cara melakukannya? :)   -  person Mohamed El Mahallawy    schedule 18.05.2015
comment
Saya menganggap jawaban yang bagus untuk itu terlalu lama untuk StackOverflow.   -  person WiredPrairie    schedule 18.05.2015


Jawaban (1)


Anda perlu memikirkan kembali arsitektur aplikasi Anda. Komponen tidak boleh mendapatkan data sendiri, Anda lebih baik jika ada sesuatu yang memberikan data kepada mereka.

Saran saya adalah melakukannya dalam tindakan navigasi, sehingga menjadi titik masuk ke tampilan mana pun. Kemudian di sini Anda dapat menyelesaikan semua data yang diperlukan dan memberi makan penyimpanan dengan data itu, setelah diselesaikan, panggil panggilan balik. Misalnya.:

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;
        }

    }

};

Dalam contoh ini saya menggunakan react-router.

person Tomas Kirda    schedule 17.05.2015
comment
Saya bersama Anda di toko menyimpan data dan memasukkannya ke komponen. Memberi +1 pada itu. Saya menyukai pendekatan Anda dalam melakukan beberapa tindakan, yang dipanggil oleh server, sebagai langkah pertama yang menunggu hingga segala sesuatunya terselesaikan. Bisakah saya tidak hanya untuk .waitFor di semua toko? - person Mohamed El Mahallawy; 18.05.2015