Вопрос по reactjs, isomorphic-javascript – Facebook React.js: как вы отображаете компоненты Statefull на сервере?

28

Я думаю я'м концептуально чего-то не хватает при рендеринге на стороне сервера с использованием React.js

Предположим, я хочу создать страницу для отображения элементов из серверной БД с полем ввода для их фильтрации.

Я хочу страницу:

который отвечает на URL, как/items?name=foobarс полем ввода React для фильтрации элементов по именис компонентом React для отображения списка отфильтрованных элементов

Предположим, у меня есть открытый REST API для запроса элементов на стороне клиента.

Концептуально, что я хочу сделать по первому требованию (GET /items?name=foobar) является :

Я хочу, чтобы мое поле ввода показывало, что пользователь передал в качестве параметра, поэтому мне нужно передать параметр запроса ('Foobar») к реакционному компоненту, какподпирать» (лайк )initialName

Итак, я попробовал это:

 // A statefull component, maintaining the value of a query field
 var ItemForm = React.createClass({
    getInitialState : function () {
        return {
            name : this.props.initialName
        };
    },
    handleInputValueChanged : function() {
        var enteredName = this.refs.query.getDOMNode().value.trim();
        this.props.onNameChanged(enteredName);
    },
    render : function () {

        return React.DOM.form({
            children : [
                React.DOM.label({
                    children : "System name"
                }),
                React.DOM.input({
                    ref : "query",
                    value : this.state.name,
                    onChange : this.handleInputValueChanged
                })
            ]
        });
    }
});
Я также должен сделать мой запрос к базе данныхна сервере получить список предметов и передать этот список какподпирать» ItemList (как 'initialItems')

Насколько я понимаю, мне нужен простой компонент для отображения списка, получая его какопора:

 // A stateless component, displaying a list of item
 var ItemList = return React.createClass({

    propTypes : {
        items : React.PropTypes.array
    },

    render : function () {
        return React.DOM.ul({
            children : _.map(this.props.items, function (item) {
                return React.DOM.li({
                    children : [
                        React.DOM.span({
                            children : ["Name : ", item.name].join(" ")
                        })]
                });
            })
        });

    }
});
Теперь мне нужен компонент, отображающий всю страницу; этот компонент должен будет поддерживать состояние всей страницы, то есть просматривать имя, введенное в поле, и выполнять запросы API для обновления элементов списка. Однако я нене понимаю, как этот компонент может иметьначальное состояние' это будет работать как на стороне сервера, так и для последующего рендеринга на стороне клиента.

Я попробовал это:

 // A statefull react component, maintaining the list of items
 var ItemPage = React.createClass({

    getInitialState : function () {
        // ?????
        // This is where I'm sure the problem lies. 
        // How can this be known both on server and client side ? 
        return {
            items : this.props.initialItems || []
        };
    },
    queryItems : function (enteredName) {

        var self = this;

        // The field was emptied, we must clear everything
        if (!enteredName) {
            this.setState({
                items : []
            });

        } else {

            // The field was changed, we want to do a query
            // then change the state to trigger a UI update. 
            // The query code is irrelevant, I think.
            doQuery(enteredName).then(function (items) {
                self.setState({
                   items : items
                });
            });

        }

    },
    render : function () {

        // I don't want to display the same view
        // if there is no results. 
        // This uses a 'state' propery of the page
        var results = null;
        if (_.isEmpty(this.state.items)) {
            results = React.DOM.div({
                ref : "results",
                children : "No results"
            });
        } else {
            results = ItemListView({
                // Here items is a 'prop', the ItemList is technically
                // stateless
                items : this.state.items
            });
        }

        return React.DOM.div({
            children : [
                ItemForm({
                    initialName : this.props.initialName,
                    onNameChanged : this.queryItems
                }),
                results
            ]
        });
    }
});

Тот'где яЯ застрял. Я могу сделать вещи на стороне сервера, используя что-то вроде

var name = // The name from the query parameters
var items = doQueryOnServerSide(name);
React.renderComponentAsString(ItemPage({
  initialName : name,
  initialItems : items
});

Но когда я пытаюсь написать на стороне клиента javascript, что мне делать? Я знаю, где я хочу, чтобы моя dom отображалась, но какие начальные реквизиты я должен передать компоненту реагирования?

React.renderComponent(ItemPage({
  initialName : ??? // Read the name parameter from URL ? 
  initialItems : ??? // I don't know yet, and I don't want to make an API call until the user entered something in the input box 
});

Большинство попыток, которые я пробовал, заканчиваются тем, что DOM былстер» на стороне клиента, с этим сообщением:

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

Обратите внимание, что удаляется только разметка моего компонента ItemList, поэтому я полагаю, чтоЭто проблема реализации моего компонента, но я неЯ действительно не знаю, с чего начать.

Я на правильном пути? Или я что-то упускаю полностью?

Спасибо

Ваш Ответ

1   ответ
14

же реквизиты, которые вы использовали для рендеринга компонента на сервере. В этом случае вам нужно передать тот же реквизит initialItems, чтобыReact.renderComponent подобрать серверную разметку (просто JSON, добавив реквизиты и поместив их в вызовrenderComponent).

Ваша общая структура чтения из initialItems, когда указано, имеет смысл для меня. Это позволяет вам либо создать компонент с предварительно загруженными данными, либо компонент, у которого их нет. То, что вам нужно, чтобы установить начальное состояние, зависит от того, что вы хотите показать в тех случаях, когда вы 'рендеринг совершенно нового компонента с нуля. (Если ты'Вы всегда берете серверную разметку, тогда вы можете просто передатьinitialName а такжеinitialItems реквизит.)

Надеюсь, что это имеет смысл.

Означает ли это, что я также должен всегда делать запрос на стороне клиента, чтобы получить список initialItems, чтобы я мог передать их как initialItems на стороне клиента? Я думал о том, чтобы на самом деле встроить json в сгенерированную на стороне сервера страницу, чтобы клиентская часть могла начать с чего-то ... потому что я нея не хочу, чтобы моя клиентская сторона выполняла тот же запрос API, который в моем случае не соответствовал бы цели рендеринга на стороне сервера ... phtrivier
Хорошо, я вижу ... Так что я быи то и другое сгенерировать разметку на стороне сервера и внедрить данные моей страницы в тег скрипта (с известным идентификатором, чтобы проанализировать его и внедрить в мой рендеринг на стороне клиента), предполагая, что React должен понимать, что разметка такая же? phtrivier
Да, если вы передадите одинаковые реквизиты на сервер и клиент, тогда разметка будет совпадать, и React увидит, что контрольная сумма совпадает. Sophie Alpert
Извините, если мне было непонятно - мое предложение было включить JSON в сгенерированную сервером страницу. Sophie Alpert

Похожие вопросы