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

React + Flux и Server-side рендеринг? (Изоморфный реактив + поток)

Какова общая практика установки начального состояния приложения с изоморфными приложениями? Без Flux я бы просто использовал что-то вроде:

var props = { }; // initial state
var html = React.renderToString(MyComponent(props);

Затем визуализируйте эту разметку через express-handlebars и отобразите ее с помощью {{{reactMarkup}}.

На стороне клиента, чтобы установить начальное состояние, я сделал бы что-то вроде этого:

if (typeof window !== 'undefined') {
    var props = JSON.parse(document.getElementById('props').innerHTML);
    React.render(MyComponent(props), document.getElementById('reactMarkup'));
}

Итак, да, в основном вы устанавливаете состояние дважды, на сервере и клиенте, однако React будет сравнивать различия и в большинстве случаев, поэтому это не повлияет на производительность путем повторной рендеринга.


Как этот принцип будет работать, когда у вас есть действия и магазины в архитектуре Flux? Внутри моего компонента я мог сделать:

getInitialState: function() {
  return AppStore.getAppState();
}

Но как установить начальное состояние в AppStore с сервера? Если я использую React.renderToString без переданных свойств, он вызовет AppStore.getAppState(), у которого ничего не будет, потому что я все еще не понимаю, как установить состояние в моем хранилище на сервере?

Обновление 5 февраля 2015 г.

Я все еще ищу чистое решение, которое не связано с использованием сторонних реализаций Flux, таких как Fluxible, Fluxxor, Reflux.

Обновление 19 августа 2016 г.

Используйте Redux.

4b9b3361

Ответ 1

Если вы готовы работать с alt.js, вы можете достичь этого с помощью alt.bootstrap и alt.flush (docs)

Я использую node js с реакцией на стороне сервера, а alt.js - на реализацию потока.

Вот как это выглядит:

var data = {}; // Get the data whatever you want and return it bootstrap ready.

// Reminder - renderToString is synchronised
var app = React.renderToString(
     AppFactory(data)
);

// In this point the react rendering was finished so we can flush the data and reset the stores

alt.flush();

В моем app.jsx

/**
 *
 */
componentWillMount: function () {

    // This beauty here is that componentWillMount is run on the server and the client so this is all we need to do. No need for other third-party isomorphic frameworks

    alt.bootstrap(
        JSON.stringify(this.props, null, 3)
    );

}

Ответ 2

Взгляните на dispatchr и связанные с Yahoo библиотеки.

Большинство реализаций потока не работают в node.js, потому что они используют одноэлементные хранилища, диспетчеры и действия, и не имеют понятия "мы закончили", что необходимо знать, когда визуализировать html и отвечать к запросу.

Библиотеки Yahoo, такие как fetchr и router, обойти это ограничение node, используя очень чистую форму инъекции зависимостей (без функций синтаксического анализа для имен аргументов или чего-либо подобного).

Вместо этого вы определяете такие функции api, как это в services/todo.js:

create: function (req, resource, params, body, config, callback) {

И действия, подобные этому в actions/createTodo.js:

module.exports = function (context, payload, done) {
    var todoStore = context.getStore(TodoStore);
...
context.dispatch('CREATE_TODO_START', newTodo);
...
context.service.create('todo', newTodo, {}, function (err, todo) {

Последняя строка косвенно вызывает функцию create в сервисах /todo.js. В этом случае косвенно может означать:

  • на сервере:
    • fetchr заполняет дополнительные аргументы, когда вы находитесь на сервере
    • Затем он вызывает ваш обратный вызов
  • на стороне клиента:
    • клиент fetchr делает http-запрос
    • fetchr на сервере перехватывает его
    • он вызывает функцию сервиса с правильными аргументами
    • он отправляет ответ обратно клиенту fetchr
    • клиентская сторона fetchr обрабатывает вызов вашего обратного вызова

Это только верхушка айсберга. Это очень сложная группа модулей, которые работают вместе, чтобы решить сложную проблему и обеспечить полезную api. Изоморфизм по своей сути усложняется в реальных случаях использования. Вот почему многие реализации потоков не поддерживают рендеринг на стороне сервера.

Вы также можете посмотреть не используя флюс. Это не имеет смысла для всех приложений и часто просто мешает. Чаще всего вам это нужно только для нескольких частей приложения, если они есть. В программировании нет серебряных пуль!

Ответ 3

FakeRainBrigand правильно, что самая большая проблема с потоком на стороне сервера - это синглтоны. Flummox исправляет эту проблему, не используя синглтоны, и позволяет вам инкапсулировать всю вашу настройку Flux в один класс многоразового использования. Затем вы просто создаете новый экземпляр для каждого запроса. В сочетании с решением маршрутизации, таким как React Router, вы можете делать полностью изоморфные приложения.

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

https://github.com/acdlite/flummox

Ответ 4

Проблема в том, что при поиске "Flux server rendering" вы сразу сталкиваетесь с этим вопросом и не упоминаете Redux, сделанное сообществом React.js rackt. Вы можете найти красиво описанную в документации Redux , почему важно рендеринг сервера, почему нам нужно отправлять начальное состояние в пределах HTML на клиент (который где Flux становится недостаточным) и как это сделать.