4

只有在 http 请求得到解决后,我才能找出让服务呈现我的反应组件的最佳方式。

例如:

组件 A <- 组件 B <- 组件 C(C 触发一个操作,该操作调用 API 并返回要渲染的数据,同时仅渲染“加载”)。

在检查我的源代码时,我只看到“正在加载”,并且出于 SEO 的目的,希望服务器等到组件 C 的调用已解决并呈现。

从理论上讲,这听起来很容易,因为服务器应该自己调用该操作并等到该操作完成然后调用react.renderToString(),如下所示:

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

但是如果多个组件发出动作调用,我需要等待多个动作解决然后调用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 回答 1

0

您需要重新考虑应用程序的架构。组件不应该自己获取数据,当某些东西向它们提供数据时你会更好。

我的建议是在导航操作中执行此操作,以便它成为任何视图的入口点。然后在这里您可以解决所有需要的数据并使用该数据馈送存储,一旦解决调用回调。例如:

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.

于 2015-05-17T23:56:47.767 回答