代码之家  ›  专栏  ›  技术社区  ›  fadedbee

ReactJS在客户端和服务器上运行不同的代码。

  •  2
  • fadedbee  · 技术社区  · 11 年前

    我正在使用 https://github.com/andreypopp/react-quickstart 在让页面在客户端上动态更新之前,在服务器端呈现页面。

    某些页面需要来自服务器的数据。在客户端上运行时,他们通过 superagent .

    在初始(服务器端)渲染期间,我希望 getInitialState 让页面直接获取数据。

    这可能吗?

    2 回复  |  直到 11 年前
        1
  •  1
  •   Jake Sendar    11 年前

    有几种方法可以解决这个问题。

    您使用的模板react quickstart使用audreypopp的react async插件来处理具有异步状态的渲染组件。README中有一节详细介绍了这种情况: https://github.com/andreypopp/react-async#rendering-async-components-on-server-with-fetched-async-state .

    基本上,您可以向的回调函数添加第三个参数 ReactAsync.renderComponentToStringWithAsyncState ,指向当前服务器状态的快照。README提供了以下示例:

    ReactAsync.renderComponentToStringWithAsyncState(
      Component(),
      function(err, markup, data) {
        res.send(ReactAsync.injectIntoMarkup(markup, data, ['./client.js']))
    })
    

    injectIntoMarkup 将预先获取的状态数据作为JSON blob注入,该blob可以在代码的其他地方引用为 window.__reactAsyncStatePacket .

    另一种方法是不使用react async。相反,你可以打电话 React.renderComponentToString ,将预获取的服务器数据作为 props .

    var markup = React.renderComponentToString(
        Item({ data: SERVER_DATA })
    );
    

    笔记 :您必须在组件代码中添加一些条件逻辑,以区分将状态直接接收为 支柱 或者通过ajax/超级代理,但应该很简单。

    现在,对于本示例,假设您使用Handlebars/Express,您可以将组件字符串注入到模板中:

    res.render('template', {
        markup: markup
    });
    

    以及您的模板:

    <div id="container">{{{ markup }}}</div>
    

    最后,为了使组件在客户端上正常工作,可以调用 React.renderComponent 正如您通常在客户端上所做的那样。React知道不替换刚从服务器呈现的组件,但是 在将来需要时重新渲染它们。

    希望这有帮助,并乐于回答任何问题!

        2
  •  0
  •   fadedbee    11 年前

    react-quickstart 已经在做我需要的事了。

    我有一个问题,我没有意识到 getInitialStateAsync 仅在使用mixin的类上调用 ReactAsync.Mixin .

    例如。

    var UserPage = React.createClass({
      mixins: [ReactAsync.Mixin],
    
      statics: {
        getUserInfo: function(username, cb) {
          superagent.get(
            'http://localhost:3000/api/users/' + username,
            function(err, res) {
              cb(err, res ? res.body : null);
            });
        }
      },
    
      getInitialStateAsync: function(cb) {
        this.type.getUserInfo(this.props.username, function(arg0, arg1) {
          cb(arg0, arg1)
        });
      },
    
      ...