Подтвердить что ты не робот

Как отображать асинхронно инициализированные компоненты на сервере

Я относительно новичок в ReactJS и был соблазнен простотой реализации серверной рендеринга, чтобы сократить время до первого твита. Я запускаю стек Node -Express-React, который предварительно создает разметку на сервере с помощью React renderComponentToString.

Он отлично работает, когда компоненты могут отображаться синхронно, однако я боюсь, когда дело доходит до реализации компонентов, заполненных ajax (однако это относится к любой асинхронной операции во время инициализации компонента, например websocket).

Возьмите пример с сайта React: http://facebook.github.io/react/tips/initial-ajax.html

componentDidMount: function() {
 $.get(this.props.source, function(result) {
  var lastGist = result[0];
  this.setState({
    username: lastGist.user.login,
    lastGistUrl: lastGist.html_url
  });
}.bind(this));

Он не будет работать на сервере, поскольку компонент componentDidMount никогда не запускается при использовании renderComponentToString. Этот простой случай можно обойти, используя ту же самую оболочку HTTP-запроса на клиенте и на сервере (вместо использования jQuery $.get), а также путем предварительной выборки данных до создания экземпляра компонента и передачи его в качестве опоры.

Однако в реальном сложном приложении асинхронные зависимости могут быть очень сложными, и предварительная выборка не очень подходит для потокового подхода к построению структур React. Как я могу реализовать асинхронный шаблон инициализации в React, который может быть отображен на сервере без фактического монтирования чего-либо (т.е. Эмуляции DOM a la PhantomJS, что является всей точкой использования renderComponentToString)?

4b9b3361

Ответ 1

Я считаю, что самый практичный способ сделать это - сделать необязательную опору для предварительно загруженных данных, например:

getInitialState: function() {
    if (this.props.initialLastGist) {
        var lastGist = this.props.initialLastGist;
        return {
            username: lastGist.user.login,
            lastGistUrl: lastGist.html_url
        };
    } else {
        return {};
    }
},

componentDidMount: function() {
    if (!this.props.initialLastGist) {
        $.get(this.props.source, function(result) {
            var lastGist = result[0];
            this.setState({
                username: lastGist.user.login,
                lastGistUrl: lastGist.html_url
            });
        }.bind(this));
    }
},

При такой настройке компонент может быть отображен немедленно, если присутствуют предварительно загруженные данные; иначе запрос AJAX будет отправлен при монтаже.

В настоящее время рендеринг сервера всегда синхронный, а componentDidMount не вызывается на сервере, поскольку он обычно включает манипуляции с DOM. Извините, у меня сейчас нет лучшего решения, но в целом вы хотите минимизировать количество HTTP-запросов на сервер, поэтому стоит подумать о своей архитектуре, чтобы вы могли собрать все данные, которые вам нужны на сервере.

Ответ 2

Вы можете посмотреть проект react-quickstart, который использует react-async и поставляется с примером рендеринга сервера. react-async предоставляет декорированный метод renderComponentToString, который предварительно выбирает асинхронное состояние и отображает его в исходную разметку. Однако вам нужно будет указать асинхронное состояние отдельно от "обычного" состояния.

Ответ 3

вы можете проверить реакцию-nexus (https://github.com/elierotenberg/react-nexus), которая поможет вам заранее объявить все ваши асинхронные зависимости.

но я понимаю, что реакция-нексус - это ваш собственный ответ на эту проблему, поэтому вы, вероятно, уже ее нашли!